shithub: freetype+ttf2subf

ref: 6b8fcd530e01ba850b2ca649d533eab8075fd042
dir: /builds/unix/ftsystem.c/

View raw version
/**************************************************************************
 *
 *  ftsystem.c                                                        1.0
 *
 *    Unix-specific FreeType low-level system interface
 *
 *    This file contains the definition of interface used by FreeType
 *    to access low-level, i.e. memory management, i/o access as well
 *    as thread synchronisation.              
 *
 *
 *  Copyright 1996-2000 by                                                   
 *  David Turner, Robert Wilhelm, and Werner Lemberg                         
 *                                                                           
 *  This file is part of the FreeType project, and may only be used          
 *  modified and distributed under the terms of the FreeType project         
 *  license, LICENSE.TXT.  By continuing to use, modify, or distribute       
 *  this file you indicate that you have read the license and                 
 *  understand and accept it fully.                                          
 *                                                                           
 **************************************************************************/

#include <ftsystem.h>
#include <fterrors.h>
#include <ftconfig.h>
#include <ftdebug.h>

/* Memory-mapping includes and definitions..                            */
/*                                                                      */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <sys/mman.h>
#ifndef MAP_FILE
#define MAP_FILE  0x00
#endif

/*
 * The prototype for munmap() is not provided on SunOS.  This needs to
 * have a check added later to see if the GNU C library is being used.
 * If so, then this prototype is not needed.
 */
#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4)
  extern int  munmap( caddr_t  addr, int  len );
#endif

#include <sys/stat.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

  /*********************************************************************/
  /*                                                                   */
  /*                       MEMORY MANAGEMENT INTERFACE                 */
  /*                                                                   */

/************************************************************************
 *
 * <FuncType>
 *    FT_Alloc_Func
 *
 * <Description>
 *    The memory allocator function type
 *
 * <Input>
 *    system    :: pointer to the system object
 *    size      :: requested size in bytes
 *
 * <Output>
 *    block     :: address of newly allocated block
 *
 * <Return>  
 *    Error code. 0 means success.
 *
 * <Note>
 *    If your allocation routine ALWAYS zeroes the new block, you
 *    should set the flag FT_SYSTEM_FLAG_ALLOC_ZEROES in your system
 *    object 'flags' field.
 *
 *    If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in
 *    your system's "system_flags" field, this function should update
 *    the "current_alloc" field of the system object.
 *
 ************************************************************************/

  static
  void*  ft_alloc( FT_Memory  memory,
                   long       size )
  {
    (void)memory;
    return malloc(size);
  }


/************************************************************************
 *
 * <FuncType>
 *    FT_Realloc_Func
 *
 * <Description>
 *    The memory reallocator function type
 *
 * <Input>
 *    system   :: pointer to the system object
 *    new_size :: new requested size in bytes
 *
 * <InOut>
 *    block    :: address of block in memory
 *
 * <Return>
 *    Error code. 0 means success.
 *
 * <Note>
 *    This function is _never_ called when the system flag 
 *    FT_SYSTEM_FLAG_NO_REALLOC is set. Instead, the engine will emulate
 *    realloc through "alloc" and "free".
 *
 *    Note that this is possible due to the fact that FreeType's
 *    "FT_Realloc" always requests the _current_ size of the reallocated
 *    block as a parameter, thus avoiding memory leaks.
 *
 *    If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in
 *    your system's "system_flags" field, this function should update
 *    the "current_alloc" field of the system object.
 *
 ************************************************************************/

  static
  void*  ft_realloc( FT_Memory  memory,
                     long       cur_size,
                     long       new_size,
                     void*      block )
  {
    (void)memory;
    (void)cur_size;

    return realloc( block, new_size );
  }


/************************************************************************
 *
 * <FuncType>
 *    FT_Free_Func
 *
 * <Description>
 *    The memory release function type
 *
 * <Input>
 *    system  :: pointer to the system object
 *    block   :: address of block in memory
 *
 * <Note>
 *    If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in
 *    your system's "system_flags" field, this function should update
 *    the "current_alloc" field of the system object.
 *
 ************************************************************************/

  static
  void  ft_free( FT_Memory  memory,
                 void*      block )
  {
    (void)memory;
    free( block );
  }

  /*********************************************************************/
  /*                                                                   */
  /*                     RESOURCE MANAGEMENT INTERFACE                 */
  /*                                                                   */

/* We use the macro STREAM_File as a convenience to extract the      */
/* system-specific stream handle from a given FreeType stream object */
#define STREAM_File(stream)  ((void*)stream->descriptor.pointer)


#undef  FT_COMPONENT
#define FT_COMPONENT  trace_io

  static
  void  ft_close_stream( FT_Stream  stream )
  {
    munmap ( stream->descriptor.pointer, stream->size );
        
    stream->descriptor.pointer = NULL;
    stream->size               = 0;
    stream->base               = 0;
  }


  extern
  int  FT_New_Stream( const char*  filepathname,
                      FT_Stream    stream )
  {
    int          file;
    struct stat  stat_buf;

    /* open the file */
    file = open( filepathname, O_RDONLY );
    if (file < 0)
    {
      FT_ERROR(( "FT.Unix.Open:" ));
      FT_ERROR(( " could not open `%s'\n", filepathname ));
      return FT_Err_Cannot_Open_Stream;
    }

    if (fstat( file, &stat_buf ) < 0)
    {
      FT_ERROR(( "FT.Unix.Open:" ));
      FT_ERROR(( " could not `fstat' file `%s'\n", filepathname ));
      goto Fail_Map;
    }
      
    stream->size     = stat_buf.st_size;
    stream->pos      = 0;
    stream->base     = mmap( NULL,
                             stream->size,
                             PROT_READ,
                             MAP_FILE | MAP_PRIVATE,
                             file,
                             0 );

    if ( (long)stream->base == -1 )
    {
      FT_ERROR(( "FT.Unix.Open:" ));
      FT_ERROR(( " Could not map file `%s'\n", filepathname ));
      goto Fail_Map;
    }

    close(file);

    stream->descriptor.pointer = stream->base;
    stream->pathname.pointer   = (char*)filepathname;
    
    stream->close = ft_close_stream;
    stream->read  = 0;
    
    FT_TRACE1(( "FT.Unix.Open:" ));
    FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
                filepathname, stream->size ));

    return FT_Err_Ok;
    
  Fail_Map:
    close(file);
    stream->base      = NULL;
    stream->size      = 0;
    stream->pos       = 0;
    
    return FT_Err_Cannot_Open_Stream;
  }


  extern
  FT_Memory  FT_New_Memory( void )
  {
    FT_Memory  memory;
    
    memory = (FT_Memory)malloc( sizeof(*memory) );
    if (memory)
    {
      memory->user    = 0;
      memory->alloc   = ft_alloc;
      memory->realloc = ft_realloc;
      memory->free    = ft_free;
    }
    return memory;
  }