ftstream.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:19k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftstream.c                                                             */
  4. /*                                                                         */
  5. /*    I/O stream support (body).                                           */
  6. /*                                                                         */
  7. /*  Copyright 2000-2001, 2002, 2004, 2005, 2006 by                         */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17. #include <ft2build.h>
  18. #include FT_INTERNAL_STREAM_H
  19. #include FT_INTERNAL_DEBUG_H
  20.   /*************************************************************************/
  21.   /*                                                                       */
  22.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  23.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  24.   /* messages during execution.                                            */
  25.   /*                                                                       */
  26. #undef  FT_COMPONENT
  27. #define FT_COMPONENT  trace_stream
  28.   FT_BASE_DEF( void )
  29.   FT_Stream_OpenMemory( FT_Stream       stream,
  30.                         const FT_Byte*  base,
  31.                         FT_ULong        size )
  32.   {
  33.     stream->base   = (FT_Byte*) base;
  34.     stream->size   = size;
  35.     stream->pos    = 0;
  36.     stream->cursor = 0;
  37.     stream->read   = 0;
  38.     stream->close  = 0;
  39.   }
  40.   FT_BASE_DEF( void )
  41.   FT_Stream_Close( FT_Stream  stream )
  42.   {
  43.     if ( stream && stream->close )
  44.       stream->close( stream );
  45.   }
  46.   FT_BASE_DEF( FT_Error )
  47.   FT_Stream_Seek( FT_Stream  stream,
  48.                   FT_ULong   pos )
  49.   {
  50.     FT_Error  error = FT_Err_Ok;
  51.     stream->pos = pos;
  52.     if ( stream->read )
  53.     {
  54.       if ( stream->read( stream, pos, 0, 0 ) )
  55.       {
  56.         FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lxn",
  57.                    pos, stream->size ));
  58.         error = FT_Err_Invalid_Stream_Operation;
  59.       }
  60.     }
  61.     /* note that seeking to the first position after the file is valid */
  62.     else if ( pos > stream->size )
  63.     {
  64.       FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lxn",
  65.                  pos, stream->size ));
  66.       error = FT_Err_Invalid_Stream_Operation;
  67.     }
  68.     return error;
  69.   }
  70.   FT_BASE_DEF( FT_Error )
  71.   FT_Stream_Skip( FT_Stream  stream,
  72.                   FT_Long    distance )
  73.   {
  74.     return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
  75.   }
  76.   FT_BASE_DEF( FT_Long )
  77.   FT_Stream_Pos( FT_Stream  stream )
  78.   {
  79.     return stream->pos;
  80.   }
  81.   FT_BASE_DEF( FT_Error )
  82.   FT_Stream_Read( FT_Stream  stream,
  83.                   FT_Byte*   buffer,
  84.                   FT_ULong   count )
  85.   {
  86.     return FT_Stream_ReadAt( stream, stream->pos, buffer, count );
  87.   }
  88.   FT_BASE_DEF( FT_Error )
  89.   FT_Stream_ReadAt( FT_Stream  stream,
  90.                     FT_ULong   pos,
  91.                     FT_Byte*   buffer,
  92.                     FT_ULong   count )
  93.   {
  94.     FT_Error  error = FT_Err_Ok;
  95.     FT_ULong  read_bytes;
  96.     if ( pos >= stream->size )
  97.     {
  98.       FT_ERROR(( "FT_Stream_ReadAt: invalid i/o; pos = 0x%lx, size = 0x%lxn",
  99.                  pos, stream->size ));
  100.       return FT_Err_Invalid_Stream_Operation;
  101.     }
  102.     if ( stream->read )
  103.       read_bytes = stream->read( stream, pos, buffer, count );
  104.     else
  105.     {
  106.       read_bytes = stream->size - pos;
  107.       if ( read_bytes > count )
  108.         read_bytes = count;
  109.       FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
  110.     }
  111.     stream->pos = pos + read_bytes;
  112.     if ( read_bytes < count )
  113.     {
  114.       FT_ERROR(( "FT_Stream_ReadAt:" ));
  115.       FT_ERROR(( " invalid read; expected %lu bytes, got %lun",
  116.                  count, read_bytes ));
  117.       error = FT_Err_Invalid_Stream_Operation;
  118.     }
  119.     return error;
  120.   }
  121.   FT_BASE_DEF( FT_ULong )
  122.   FT_Stream_TryRead( FT_Stream  stream,
  123.                      FT_Byte*   buffer,
  124.                      FT_ULong   count )
  125.   {
  126.     FT_ULong  read_bytes = 0;
  127.     if ( stream->pos >= stream->size )
  128.       goto Exit;
  129.     if ( stream->read )
  130.       read_bytes = stream->read( stream, stream->pos, buffer, count );
  131.     else
  132.     {
  133.       read_bytes = stream->size - stream->pos;
  134.       if ( read_bytes > count )
  135.         read_bytes = count;
  136.       FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
  137.     }
  138.     stream->pos += read_bytes;
  139.   Exit:
  140.     return read_bytes;
  141.   }
  142.   FT_BASE_DEF( FT_Error )
  143.   FT_Stream_ExtractFrame( FT_Stream  stream,
  144.                           FT_ULong   count,
  145.                           FT_Byte**  pbytes )
  146.   {
  147.     FT_Error  error;
  148.     error = FT_Stream_EnterFrame( stream, count );
  149.     if ( !error )
  150.     {
  151.       *pbytes = (FT_Byte*)stream->cursor;
  152.       /* equivalent to FT_Stream_ExitFrame(), with no memory block release */
  153.       stream->cursor = 0;
  154.       stream->limit  = 0;
  155.     }
  156.     return error;
  157.   }
  158.   FT_BASE_DEF( void )
  159.   FT_Stream_ReleaseFrame( FT_Stream  stream,
  160.                           FT_Byte**  pbytes )
  161.   {
  162.     if ( stream->read )
  163.     {
  164.       FT_Memory  memory = stream->memory;
  165. #ifdef FT_DEBUG_MEMORY
  166.       ft_mem_free( memory, *pbytes );
  167.       *pbytes = NULL;
  168. #else
  169.       FT_FREE( *pbytes );
  170. #endif
  171.     }
  172.     *pbytes = 0;
  173.   }
  174.   FT_BASE_DEF( FT_Error )
  175.   FT_Stream_EnterFrame( FT_Stream  stream,
  176.                         FT_ULong   count )
  177.   {
  178.     FT_Error  error = FT_Err_Ok;
  179.     FT_ULong  read_bytes;
  180.     /* check for nested frame access */
  181.     FT_ASSERT( stream && stream->cursor == 0 );
  182.     if ( stream->read )
  183.     {
  184.       /* allocate the frame in memory */
  185.       FT_Memory  memory = stream->memory;
  186. #ifdef FT_DEBUG_MEMORY
  187.       /* assume _ft_debug_file and _ft_debug_lineno are already set */
  188.       stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );
  189.       if ( error )
  190.         goto Exit;
  191. #else
  192.       if ( FT_QALLOC( stream->base, count ) )
  193.         goto Exit;
  194. #endif
  195.       /* read it */
  196.       read_bytes = stream->read( stream, stream->pos,
  197.                                  stream->base, count );
  198.       if ( read_bytes < count )
  199.       {
  200.         FT_ERROR(( "FT_Stream_EnterFrame:" ));
  201.         FT_ERROR(( " invalid read; expected %lu bytes, got %lun",
  202.                    count, read_bytes ));
  203.         FT_FREE( stream->base );
  204.         error = FT_Err_Invalid_Stream_Operation;
  205.       }
  206.       stream->cursor = stream->base;
  207.       stream->limit  = stream->cursor + count;
  208.       stream->pos   += read_bytes;
  209.     }
  210.     else
  211.     {
  212.       /* check current and new position */
  213.       if ( stream->pos >= stream->size        ||
  214.            stream->pos + count > stream->size )
  215.       {
  216.         FT_ERROR(( "FT_Stream_EnterFrame:" ));
  217.         FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lxn",
  218.                    stream->pos, count, stream->size ));
  219.         error = FT_Err_Invalid_Stream_Operation;
  220.         goto Exit;
  221.       }
  222.       /* set cursor */
  223.       stream->cursor = stream->base + stream->pos;
  224.       stream->limit  = stream->cursor + count;
  225.       stream->pos   += count;
  226.     }
  227.   Exit:
  228.     return error;
  229.   }
  230.   FT_BASE_DEF( void )
  231.   FT_Stream_ExitFrame( FT_Stream  stream )
  232.   {
  233.     /* IMPORTANT: The assertion stream->cursor != 0 was removed, given    */
  234.     /*            that it is possible to access a frame of length 0 in    */
  235.     /*            some weird fonts (usually, when accessing an array of   */
  236.     /*            0 records, like in some strange kern tables).           */
  237.     /*                                                                    */
  238.     /*  In this case, the loader code handles the 0-length table          */
  239.     /*  gracefully; however, stream.cursor is really set to 0 by the      */
  240.     /*  FT_Stream_EnterFrame() call, and this is not an error.            */
  241.     /*                                                                    */
  242.     FT_ASSERT( stream );
  243.     if ( stream->read )
  244.     {
  245.       FT_Memory  memory = stream->memory;
  246. #ifdef FT_DEBUG_MEMORY
  247.       ft_mem_free( memory, stream->base );
  248.       stream->base = NULL;
  249. #else
  250.       FT_FREE( stream->base );
  251. #endif
  252.     }
  253.     stream->cursor = 0;
  254.     stream->limit  = 0;
  255.   }
  256.   FT_BASE_DEF( FT_Char )
  257.   FT_Stream_GetChar( FT_Stream  stream )
  258.   {
  259.     FT_Char  result;
  260.     FT_ASSERT( stream && stream->cursor );
  261.     result = 0;
  262.     if ( stream->cursor < stream->limit )
  263.       result = *stream->cursor++;
  264.     return result;
  265.   }
  266.   FT_BASE_DEF( FT_Short )
  267.   FT_Stream_GetShort( FT_Stream  stream )
  268.   {
  269.     FT_Byte*  p;
  270.     FT_Short  result;
  271.     FT_ASSERT( stream && stream->cursor );
  272.     result         = 0;
  273.     p              = stream->cursor;
  274.     if ( p + 1 < stream->limit )
  275.       result       = FT_NEXT_SHORT( p );
  276.     stream->cursor = p;
  277.     return result;
  278.   }
  279.   FT_BASE_DEF( FT_Short )
  280.   FT_Stream_GetShortLE( FT_Stream  stream )
  281.   {
  282.     FT_Byte*  p;
  283.     FT_Short  result;
  284.     FT_ASSERT( stream && stream->cursor );
  285.     result         = 0;
  286.     p              = stream->cursor;
  287.     if ( p + 1 < stream->limit )
  288.       result       = FT_NEXT_SHORT_LE( p );
  289.     stream->cursor = p;
  290.     return result;
  291.   }
  292.   FT_BASE_DEF( FT_Long )
  293.   FT_Stream_GetOffset( FT_Stream  stream )
  294.   {
  295.     FT_Byte*  p;
  296.     FT_Long   result;
  297.     FT_ASSERT( stream && stream->cursor );
  298.     result         = 0;
  299.     p              = stream->cursor;
  300.     if ( p + 2 < stream->limit )
  301.       result       = FT_NEXT_OFF3( p );
  302.     stream->cursor = p;
  303.     return result;
  304.   }
  305.   FT_BASE_DEF( FT_Long )
  306.   FT_Stream_GetLong( FT_Stream  stream )
  307.   {
  308.     FT_Byte*  p;
  309.     FT_Long   result;
  310.     FT_ASSERT( stream && stream->cursor );
  311.     result         = 0;
  312.     p              = stream->cursor;
  313.     if ( p + 3 < stream->limit )
  314.       result       = FT_NEXT_LONG( p );
  315.     stream->cursor = p;
  316.     return result;
  317.   }
  318.   FT_BASE_DEF( FT_Long )
  319.   FT_Stream_GetLongLE( FT_Stream  stream )
  320.   {
  321.     FT_Byte*  p;
  322.     FT_Long   result;
  323.     FT_ASSERT( stream && stream->cursor );
  324.     result         = 0;
  325.     p              = stream->cursor;
  326.     if ( p + 3 < stream->limit )
  327.       result       = FT_NEXT_LONG_LE( p );
  328.     stream->cursor = p;
  329.     return result;
  330.   }
  331.   FT_BASE_DEF( FT_Char )
  332.   FT_Stream_ReadChar( FT_Stream  stream,
  333.                       FT_Error*  error )
  334.   {
  335.     FT_Byte  result = 0;
  336.     FT_ASSERT( stream );
  337.     *error = FT_Err_Ok;
  338.     if ( stream->read )
  339.     {
  340.       if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
  341.         goto Fail;
  342.     }
  343.     else
  344.     {
  345.       if ( stream->pos < stream->size )
  346.         result = stream->base[stream->pos];
  347.       else
  348.         goto Fail;
  349.     }
  350.     stream->pos++;
  351.     return result;
  352.   Fail:
  353.     *error = FT_Err_Invalid_Stream_Operation;
  354.     FT_ERROR(( "FT_Stream_ReadChar: invalid i/o; pos = 0x%lx, size = 0x%lxn",
  355.                stream->pos, stream->size ));
  356.     return 0;
  357.   }
  358.   FT_BASE_DEF( FT_Short )
  359.   FT_Stream_ReadShort( FT_Stream  stream,
  360.                        FT_Error*  error )
  361.   {
  362.     FT_Byte   reads[2];
  363.     FT_Byte*  p = 0;
  364.     FT_Short  result = 0;
  365.     FT_ASSERT( stream );
  366.     *error = FT_Err_Ok;
  367.     if ( stream->pos + 1 < stream->size )
  368.     {
  369.       if ( stream->read )
  370.       {
  371.         if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
  372.           goto Fail;
  373.         p = reads;
  374.       }
  375.       else
  376.       {
  377.         p = stream->base + stream->pos;
  378.       }
  379.       if ( p )
  380.         result = FT_NEXT_SHORT( p );
  381.     }
  382.     else
  383.       goto Fail;
  384.     stream->pos += 2;
  385.     return result;
  386.   Fail:
  387.     *error = FT_Err_Invalid_Stream_Operation;
  388.     FT_ERROR(( "FT_Stream_ReadShort:" ));
  389.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lxn",
  390.                stream->pos, stream->size ));
  391.     return 0;
  392.   }
  393.   FT_BASE_DEF( FT_Short )
  394.   FT_Stream_ReadShortLE( FT_Stream  stream,
  395.                          FT_Error*  error )
  396.   {
  397.     FT_Byte   reads[2];
  398.     FT_Byte*  p = 0;
  399.     FT_Short  result = 0;
  400.     FT_ASSERT( stream );
  401.     *error = FT_Err_Ok;
  402.     if ( stream->pos + 1 < stream->size )
  403.     {
  404.       if ( stream->read )
  405.       {
  406.         if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
  407.           goto Fail;
  408.         p = reads;
  409.       }
  410.       else
  411.       {
  412.         p = stream->base + stream->pos;
  413.       }
  414.       if ( p )
  415.         result = FT_NEXT_SHORT_LE( p );
  416.     }
  417.     else
  418.       goto Fail;
  419.     stream->pos += 2;
  420.     return result;
  421.   Fail:
  422.     *error = FT_Err_Invalid_Stream_Operation;
  423.     FT_ERROR(( "FT_Stream_ReadShortLE:" ));
  424.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lxn",
  425.                stream->pos, stream->size ));
  426.     return 0;
  427.   }
  428.   FT_BASE_DEF( FT_Long )
  429.   FT_Stream_ReadOffset( FT_Stream  stream,
  430.                         FT_Error*  error )
  431.   {
  432.     FT_Byte   reads[3];
  433.     FT_Byte*  p = 0;
  434.     FT_Long   result = 0;
  435.     FT_ASSERT( stream );
  436.     *error = FT_Err_Ok;
  437.     if ( stream->pos + 2 < stream->size )
  438.     {
  439.       if ( stream->read )
  440.       {
  441.         if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
  442.           goto Fail;
  443.         p = reads;
  444.       }
  445.       else
  446.       {
  447.         p = stream->base + stream->pos;
  448.       }
  449.       if ( p )
  450.         result = FT_NEXT_OFF3( p );
  451.     }
  452.     else
  453.       goto Fail;
  454.     stream->pos += 3;
  455.     return result;
  456.   Fail:
  457.     *error = FT_Err_Invalid_Stream_Operation;
  458.     FT_ERROR(( "FT_Stream_ReadOffset:" ));
  459.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lxn",
  460.                stream->pos, stream->size ));
  461.     return 0;
  462.   }
  463.   FT_BASE_DEF( FT_Long )
  464.   FT_Stream_ReadLong( FT_Stream  stream,
  465.                       FT_Error*  error )
  466.   {
  467.     FT_Byte   reads[4];
  468.     FT_Byte*  p = 0;
  469.     FT_Long   result = 0;
  470.     FT_ASSERT( stream );
  471.     *error = FT_Err_Ok;
  472.     if ( stream->pos + 3 < stream->size )
  473.     {
  474.       if ( stream->read )
  475.       {
  476.         if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
  477.           goto Fail;
  478.         p = reads;
  479.       }
  480.       else
  481.       {
  482.         p = stream->base + stream->pos;
  483.       }
  484.       if ( p )
  485.         result = FT_NEXT_LONG( p );
  486.     }
  487.     else
  488.       goto Fail;
  489.     stream->pos += 4;
  490.     return result;
  491.   Fail:
  492.     FT_ERROR(( "FT_Stream_ReadLong: invalid i/o; pos = 0x%lx, size = 0x%lxn",
  493.                stream->pos, stream->size ));
  494.     *error = FT_Err_Invalid_Stream_Operation;
  495.     return 0;
  496.   }
  497.   FT_BASE_DEF( FT_Long )
  498.   FT_Stream_ReadLongLE( FT_Stream  stream,
  499.                         FT_Error*  error )
  500.   {
  501.     FT_Byte   reads[4];
  502.     FT_Byte*  p = 0;
  503.     FT_Long   result = 0;
  504.     FT_ASSERT( stream );
  505.     *error = FT_Err_Ok;
  506.     if ( stream->pos + 3 < stream->size )
  507.     {
  508.       if ( stream->read )
  509.       {
  510.         if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
  511.           goto Fail;
  512.         p = reads;
  513.       }
  514.       else
  515.       {
  516.         p = stream->base + stream->pos;
  517.       }
  518.       if ( p )
  519.         result = FT_NEXT_LONG_LE( p );
  520.     }
  521.     else
  522.       goto Fail;
  523.     stream->pos += 4;
  524.     return result;
  525.   Fail:
  526.     FT_ERROR(( "FT_Stream_ReadLongLE:" ));
  527.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lxn",
  528.                stream->pos, stream->size ));
  529.     *error = FT_Err_Invalid_Stream_Operation;
  530.     return 0;
  531.   }
  532.   FT_BASE_DEF( FT_Error )
  533.   FT_Stream_ReadFields( FT_Stream              stream,
  534.                         const FT_Frame_Field*  fields,
  535.                         void*                  structure )
  536.   {
  537.     FT_Error  error;
  538.     FT_Bool   frame_accessed = 0;
  539.     FT_Byte*  cursor = stream->cursor;
  540.     if ( !fields || !stream )
  541.       return FT_Err_Invalid_Argument;
  542.     error = FT_Err_Ok;
  543.     do
  544.     {
  545.       FT_ULong  value;
  546.       FT_Int    sign_shift;
  547.       FT_Byte*  p;
  548.       switch ( fields->value )
  549.       {
  550.       case ft_frame_start:  /* access a new frame */
  551.         error = FT_Stream_EnterFrame( stream, fields->offset );
  552.         if ( error )
  553.           goto Exit;
  554.         frame_accessed = 1;
  555.         cursor         = stream->cursor;
  556.         fields++;
  557.         continue;  /* loop! */
  558.       case ft_frame_bytes:  /* read a byte sequence */
  559.       case ft_frame_skip:   /* skip some bytes      */
  560.         {
  561.           FT_UInt  len = fields->size;
  562.           if ( cursor + len > stream->limit )
  563.           {
  564.             error = FT_Err_Invalid_Stream_Operation;
  565.             goto Exit;
  566.           }
  567.           if ( fields->value == ft_frame_bytes )
  568.           {
  569.             p = (FT_Byte*)structure + fields->offset;
  570.             FT_MEM_COPY( p, cursor, len );
  571.           }
  572.           cursor += len;
  573.           fields++;
  574.           continue;
  575.         }
  576.       case ft_frame_byte:
  577.       case ft_frame_schar:  /* read a single byte */
  578.         value = FT_NEXT_BYTE(cursor);
  579.         sign_shift = 24;
  580.         break;
  581.       case ft_frame_short_be:
  582.       case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
  583.         value = FT_NEXT_USHORT(cursor);
  584.         sign_shift = 16;
  585.         break;
  586.       case ft_frame_short_le:
  587.       case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
  588.         value = FT_NEXT_USHORT_LE(cursor);
  589.         sign_shift = 16;
  590.         break;
  591.       case ft_frame_long_be:
  592.       case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
  593.         value = FT_NEXT_ULONG(cursor);
  594.         sign_shift = 0;
  595.         break;
  596.       case ft_frame_long_le:
  597.       case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
  598.         value = FT_NEXT_ULONG_LE(cursor);
  599.         sign_shift = 0;
  600.         break;
  601.       case ft_frame_off3_be:
  602.       case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
  603.         value = FT_NEXT_UOFF3(cursor);
  604.         sign_shift = 8;
  605.         break;
  606.       case ft_frame_off3_le:
  607.       case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
  608.         value = FT_NEXT_UOFF3_LE(cursor);
  609.         sign_shift = 8;
  610.         break;
  611.       default:
  612.         /* otherwise, exit the loop */
  613.         stream->cursor = cursor;
  614.         goto Exit;
  615.       }
  616.       /* now, compute the signed value is necessary */
  617.       if ( fields->value & FT_FRAME_OP_SIGNED )
  618.         value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
  619.       /* finally, store the value in the object */
  620.       p = (FT_Byte*)structure + fields->offset;
  621.       switch ( fields->size )
  622.       {
  623.       case (8 / FT_CHAR_BIT):
  624.         *(FT_Byte*)p = (FT_Byte)value;
  625.         break;
  626.       case (16 / FT_CHAR_BIT):
  627.         *(FT_UShort*)p = (FT_UShort)value;
  628.         break;
  629.       case (32 / FT_CHAR_BIT):
  630.         *(FT_UInt32*)p = (FT_UInt32)value;
  631.         break;
  632.       default:  /* for 64-bit systems */
  633.         *(FT_ULong*)p = (FT_ULong)value;
  634.       }
  635.       /* go to next field */
  636.       fields++;
  637.     }
  638.     while ( 1 );
  639.   Exit:
  640.     /* close the frame if it was opened by this read */
  641.     if ( frame_accessed )
  642.       FT_Stream_ExitFrame( stream );
  643.     return error;
  644.   }
  645. /* END */