misc/libfreetype/builds/amiga/src/base/ftsystem.c
changeset 9431 0f5961910e27
parent 9357 a501f5ec7b34
parent 9429 7a97a554ac80
child 9433 f0a8ac191839
equal deleted inserted replaced
9357:a501f5ec7b34 9431:0f5961910e27
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  ftsystem.c                                                             */
       
     4 /*                                                                         */
       
     5 /*    Amiga-specific FreeType low-level system interface (body).           */
       
     6 /*                                                                         */
       
     7 /*  Copyright 1996-2001, 2002, 2005, 2006, 2007, 2010 by                   */
       
     8 /*  David Turner, Robert Wilhelm, Werner Lemberg and Detlef Würkner.       */
       
     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 
       
    18   /*************************************************************************/
       
    19   /*                                                                       */
       
    20   /* This file contains the Amiga interface used by FreeType to access     */
       
    21   /* low-level, i.e. memory management, i/o access as well as thread       */
       
    22   /* synchronisation.                                                      */
       
    23   /*                                                                       */
       
    24   /*************************************************************************/
       
    25 
       
    26 
       
    27   /*************************************************************************/
       
    28   /*                                                                       */
       
    29   /* Maintained by Detlef Würkner <TetiSoft@apg.lahn.de>                   */
       
    30   /*                                                                       */
       
    31   /* Based on the original ftsystem.c,                                     */
       
    32   /* modified to avoid fopen(), fclose(), fread(), fseek(), ftell(),       */
       
    33   /* malloc(), realloc(), and free().                                      */
       
    34   /*                                                                       */
       
    35   /* Those C library functions are often not thread-safe or cant be        */
       
    36   /* used in a shared Amiga library. If that's not a problem for you,       */
       
    37   /* you can of course use the default ftsystem.c with C library calls     */
       
    38   /* instead.                                                              */
       
    39   /*                                                                       */
       
    40   /* This implementation needs exec V39+ because it uses AllocPooled() etc */
       
    41   /*                                                                       */
       
    42   /*************************************************************************/
       
    43 
       
    44 #define __NOLIBBASE__
       
    45 #define __NOGLOBALIFACE__
       
    46 #define __USE_INLINE__
       
    47 #include <proto/exec.h>
       
    48 #include <dos/stdio.h>
       
    49 #include <proto/dos.h>
       
    50 #ifdef __amigaos4__
       
    51 extern struct ExecIFace *IExec;
       
    52 extern struct DOSIFace  *IDOS;
       
    53 #else
       
    54 extern struct Library   *SysBase;
       
    55 extern struct Library   *DOSBase;
       
    56 #endif
       
    57 
       
    58 #define IOBUF_SIZE 512
       
    59 
       
    60 /* structure that helps us to avoid
       
    61  * useless calls of Seek() and Read()
       
    62  */
       
    63 struct SysFile
       
    64 {
       
    65   BPTR  file;
       
    66   ULONG iobuf_start;
       
    67   ULONG iobuf_end;
       
    68   UBYTE iobuf[IOBUF_SIZE];
       
    69 };
       
    70 
       
    71 #ifndef __amigaos4__
       
    72 /* C implementation of AllocVecPooled (see autodoc exec/AllocPooled) */
       
    73 APTR
       
    74 Alloc_VecPooled( APTR   poolHeader,
       
    75                  ULONG  memSize )
       
    76 {
       
    77   ULONG  newSize = memSize + sizeof ( ULONG );
       
    78   ULONG  *mem = AllocPooled( poolHeader, newSize );
       
    79 
       
    80   if ( !mem )
       
    81     return NULL;
       
    82   *mem = newSize;
       
    83   return mem + 1;
       
    84 }
       
    85 
       
    86 /* C implementation of FreeVecPooled (see autodoc exec/AllocPooled) */
       
    87 void
       
    88 Free_VecPooled( APTR  poolHeader,
       
    89                 APTR  memory )
       
    90 {
       
    91   ULONG  *realmem = (ULONG *)memory - 1;
       
    92 
       
    93   FreePooled( poolHeader, realmem, *realmem );
       
    94 }
       
    95 #endif
       
    96 
       
    97 #include <ft2build.h>
       
    98 #include FT_CONFIG_CONFIG_H
       
    99 #include FT_INTERNAL_DEBUG_H
       
   100 #include FT_SYSTEM_H
       
   101 #include FT_ERRORS_H
       
   102 #include FT_TYPES_H
       
   103 
       
   104 #include <stdio.h>
       
   105 #include <stdlib.h>
       
   106 #include <string.h>
       
   107 
       
   108 
       
   109   /*************************************************************************/
       
   110   /*                                                                       */
       
   111   /*                       MEMORY MANAGEMENT INTERFACE                     */
       
   112   /*                                                                       */
       
   113   /*************************************************************************/
       
   114 
       
   115   /*************************************************************************/
       
   116   /*                                                                       */
       
   117   /* It is not necessary to do any error checking for the                  */
       
   118   /* allocation-related functions.  This is done by the higher level       */
       
   119   /* routines like ft_mem_alloc() or ft_mem_realloc().                     */
       
   120   /*                                                                       */
       
   121   /*************************************************************************/
       
   122 
       
   123 
       
   124   /*************************************************************************/
       
   125   /*                                                                       */
       
   126   /* <Function>                                                            */
       
   127   /*    ft_alloc                                                           */
       
   128   /*                                                                       */
       
   129   /* <Description>                                                         */
       
   130   /*    The memory allocation function.                                    */
       
   131   /*                                                                       */
       
   132   /* <Input>                                                               */
       
   133   /*    memory :: A pointer to the memory object.                          */
       
   134   /*                                                                       */
       
   135   /*    size   :: The requested size in bytes.                             */
       
   136   /*                                                                       */
       
   137   /* <Return>                                                              */
       
   138   /*    The address of newly allocated block.                              */
       
   139   /*                                                                       */
       
   140   FT_CALLBACK_DEF( void* )
       
   141   ft_alloc( FT_Memory  memory,
       
   142             long       size )
       
   143   {
       
   144 #ifdef __amigaos4__
       
   145     return AllocVecPooled( memory->user, size );
       
   146 #else
       
   147     return Alloc_VecPooled( memory->user, size );
       
   148 #endif
       
   149   }
       
   150 
       
   151 
       
   152   /*************************************************************************/
       
   153   /*                                                                       */
       
   154   /* <Function>                                                            */
       
   155   /*    ft_realloc                                                         */
       
   156   /*                                                                       */
       
   157   /* <Description>                                                         */
       
   158   /*    The memory reallocation function.                                  */
       
   159   /*                                                                       */
       
   160   /* <Input>                                                               */
       
   161   /*    memory   :: A pointer to the memory object.                        */
       
   162   /*                                                                       */
       
   163   /*    cur_size :: The current size of the allocated memory block.        */
       
   164   /*                                                                       */
       
   165   /*    new_size :: The newly requested size in bytes.                     */
       
   166   /*                                                                       */
       
   167   /*    block    :: The current address of the block in memory.            */
       
   168   /*                                                                       */
       
   169   /* <Return>                                                              */
       
   170   /*    The address of the reallocated memory block.                       */
       
   171   /*                                                                       */
       
   172   FT_CALLBACK_DEF( void* )
       
   173   ft_realloc( FT_Memory  memory,
       
   174               long       cur_size,
       
   175               long       new_size,
       
   176               void*      block )
       
   177   {
       
   178     void* new_block;
       
   179 
       
   180 #ifdef __amigaos4__
       
   181     new_block = AllocVecPooled ( memory->user, new_size );
       
   182 #else
       
   183     new_block = Alloc_VecPooled ( memory->user, new_size );
       
   184 #endif
       
   185     if ( new_block != NULL )
       
   186     {
       
   187       CopyMem ( block, new_block,
       
   188                 ( new_size > cur_size ) ? cur_size : new_size );
       
   189 #ifdef __amigaos4__
       
   190       FreeVecPooled ( memory->user, block );
       
   191 #else
       
   192       Free_VecPooled ( memory->user, block );
       
   193 #endif
       
   194     }
       
   195     return new_block;
       
   196   }
       
   197 
       
   198 
       
   199   /*************************************************************************/
       
   200   /*                                                                       */
       
   201   /* <Function>                                                            */
       
   202   /*    ft_free                                                            */
       
   203   /*                                                                       */
       
   204   /* <Description>                                                         */
       
   205   /*    The memory release function.                                       */
       
   206   /*                                                                       */
       
   207   /* <Input>                                                               */
       
   208   /*    memory  :: A pointer to the memory object.                         */
       
   209   /*                                                                       */
       
   210   /*    block   :: The address of block in memory to be freed.             */
       
   211   /*                                                                       */
       
   212   FT_CALLBACK_DEF( void )
       
   213   ft_free( FT_Memory  memory,
       
   214            void*      block )
       
   215   {
       
   216 #ifdef __amigaos4__
       
   217     FreeVecPooled( memory->user, block );
       
   218 #else
       
   219     Free_VecPooled( memory->user, block );
       
   220 #endif
       
   221   }
       
   222 
       
   223 
       
   224   /*************************************************************************/
       
   225   /*                                                                       */
       
   226   /*                     RESOURCE MANAGEMENT INTERFACE                     */
       
   227   /*                                                                       */
       
   228   /*************************************************************************/
       
   229 
       
   230 
       
   231   /*************************************************************************/
       
   232   /*                                                                       */
       
   233   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
   234   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
   235   /* messages during execution.                                            */
       
   236   /*                                                                       */
       
   237 #undef  FT_COMPONENT
       
   238 #define FT_COMPONENT  trace_io
       
   239 
       
   240   /* We use the macro STREAM_FILE for convenience to extract the       */
       
   241   /* system-specific stream handle from a given FreeType stream object */
       
   242 #define STREAM_FILE( stream )  ( (struct SysFile *)stream->descriptor.pointer )
       
   243 
       
   244 
       
   245   /*************************************************************************/
       
   246   /*                                                                       */
       
   247   /* <Function>                                                            */
       
   248   /*    ft_amiga_stream_close                                              */
       
   249   /*                                                                       */
       
   250   /* <Description>                                                         */
       
   251   /*    The function to close a stream.                                    */
       
   252   /*                                                                       */
       
   253   /* <Input>                                                               */
       
   254   /*    stream :: A pointer to the stream object.                          */
       
   255   /*                                                                       */
       
   256   FT_CALLBACK_DEF( void )
       
   257   ft_amiga_stream_close( FT_Stream  stream )
       
   258   {
       
   259     struct SysFile* sysfile;
       
   260 
       
   261     sysfile = STREAM_FILE( stream );
       
   262     Close ( sysfile->file );
       
   263     FreeMem ( sysfile, sizeof ( struct SysFile ));
       
   264 
       
   265     stream->descriptor.pointer = NULL;
       
   266     stream->size               = 0;
       
   267     stream->base               = 0;
       
   268   }
       
   269 
       
   270 
       
   271   /*************************************************************************/
       
   272   /*                                                                       */
       
   273   /* <Function>                                                            */
       
   274   /*    ft_amiga_stream_io                                                 */
       
   275   /*                                                                       */
       
   276   /* <Description>                                                         */
       
   277   /*    The function to open a stream.                                     */
       
   278   /*                                                                       */
       
   279   /* <Input>                                                               */
       
   280   /*    stream :: A pointer to the stream object.                          */
       
   281   /*                                                                       */
       
   282   /*    offset :: The position in the data stream to start reading.        */
       
   283   /*                                                                       */
       
   284   /*    buffer :: The address of buffer to store the read data.            */
       
   285   /*                                                                       */
       
   286   /*    count  :: The number of bytes to read from the stream.             */
       
   287   /*                                                                       */
       
   288   /* <Return>                                                              */
       
   289   /*    The number of bytes actually read.                                 */
       
   290   /*                                                                       */
       
   291   FT_CALLBACK_DEF( unsigned long )
       
   292   ft_amiga_stream_io( FT_Stream       stream,
       
   293                       unsigned long   offset,
       
   294                       unsigned char*  buffer,
       
   295                       unsigned long   count )
       
   296   {
       
   297     struct SysFile* sysfile;
       
   298     unsigned long   read_bytes;
       
   299 
       
   300     if ( count != 0 )
       
   301     {
       
   302       sysfile = STREAM_FILE( stream );
       
   303 
       
   304       /* handle the seek */
       
   305       if ( (offset < sysfile->iobuf_start) || (offset + count > sysfile->iobuf_end) )
       
   306       {
       
   307         /* requested offset implies we need a buffer refill */
       
   308         if ( !sysfile->iobuf_end || offset != sysfile->iobuf_end )
       
   309         {
       
   310           /* a physical seek is necessary */
       
   311           Seek( sysfile->file, offset, OFFSET_BEGINNING );
       
   312         }
       
   313         sysfile->iobuf_start = offset;
       
   314         sysfile->iobuf_end = 0; /* trigger a buffer refill */
       
   315       }
       
   316 
       
   317       /* handle the read */
       
   318       if ( offset + count <= sysfile->iobuf_end )
       
   319       {
       
   320         /* we have buffer and requested bytes are all inside our buffer */
       
   321         CopyMem( &sysfile->iobuf[offset - sysfile->iobuf_start], buffer, count );
       
   322         read_bytes = count;
       
   323       }
       
   324       else
       
   325       {
       
   326         /* (re)fill buffer */
       
   327         if ( count <= IOBUF_SIZE )
       
   328         {
       
   329           /* requested bytes is a subset of the buffer */
       
   330           read_bytes = Read( sysfile->file, sysfile->iobuf, IOBUF_SIZE );
       
   331           if ( read_bytes == -1UL )
       
   332           {
       
   333             /* error */
       
   334             read_bytes = 0;
       
   335           }
       
   336           else
       
   337           {
       
   338             sysfile->iobuf_end = offset + read_bytes;
       
   339             CopyMem( sysfile->iobuf, buffer, count );
       
   340             if ( read_bytes > count )
       
   341             {
       
   342               read_bytes = count;
       
   343             }
       
   344           }
       
   345         }
       
   346         else
       
   347         {
       
   348           /* we actually need more than our buffer can hold, so we decide
       
   349           ** to do a single big read, and then copy the last IOBUF_SIZE
       
   350           ** bytes of that to our internal buffer for later use */
       
   351           read_bytes = Read( sysfile->file, buffer, count );
       
   352           if ( read_bytes == -1UL )
       
   353           {
       
   354             /* error */
       
   355             read_bytes = 0;
       
   356           }
       
   357           else
       
   358           {
       
   359             ULONG bufsize;
       
   360 
       
   361             bufsize = ( read_bytes > IOBUF_SIZE ) ? IOBUF_SIZE : read_bytes;
       
   362             sysfile->iobuf_end = offset + read_bytes;
       
   363             sysfile->iobuf_start = sysfile->iobuf_end - bufsize;
       
   364             CopyMem( &buffer[read_bytes - bufsize] , sysfile->iobuf, bufsize );
       
   365           }
       
   366         }
       
   367       }
       
   368     }
       
   369     else
       
   370     {
       
   371       read_bytes = 0;
       
   372     }
       
   373 
       
   374     return read_bytes;
       
   375   }
       
   376 
       
   377 
       
   378   /* documentation is in ftobjs.h */
       
   379 
       
   380   FT_BASE_DEF( FT_Error )
       
   381   FT_Stream_Open( FT_Stream    stream,
       
   382                   const char*  filepathname )
       
   383   {
       
   384     struct FileInfoBlock*  fib;
       
   385     struct SysFile*        sysfile;
       
   386 
       
   387 
       
   388     if ( !stream )
       
   389       return FT_Err_Invalid_Stream_Handle;
       
   390 
       
   391 #ifdef __amigaos4__
       
   392     sysfile = AllocMem ( sizeof (struct SysFile ), MEMF_SHARED );
       
   393 #else
       
   394     sysfile = AllocMem ( sizeof (struct SysFile ), MEMF_PUBLIC );
       
   395 #endif
       
   396     if ( !sysfile )
       
   397     {
       
   398       FT_ERROR(( "FT_Stream_Open:" ));
       
   399       FT_ERROR(( " could not open `%s'\n", filepathname ));
       
   400 
       
   401       return FT_Err_Cannot_Open_Resource;
       
   402     }
       
   403     sysfile->file = Open( (STRPTR)filepathname, MODE_OLDFILE );
       
   404     if ( !sysfile->file )
       
   405     {
       
   406       FreeMem ( sysfile, sizeof ( struct SysFile ));
       
   407       FT_ERROR(( "FT_Stream_Open:" ));
       
   408       FT_ERROR(( " could not open `%s'\n", filepathname ));
       
   409 
       
   410       return FT_Err_Cannot_Open_Resource;
       
   411     }
       
   412 
       
   413     fib = AllocDosObject( DOS_FIB, NULL );
       
   414     if ( !fib )
       
   415     {
       
   416       Close ( sysfile->file );
       
   417       FreeMem ( sysfile, sizeof ( struct SysFile ));
       
   418       FT_ERROR(( "FT_Stream_Open:" ));
       
   419       FT_ERROR(( " could not open `%s'\n", filepathname ));
       
   420 
       
   421       return FT_Err_Cannot_Open_Resource;
       
   422     }
       
   423     if ( !( ExamineFH( sysfile->file, fib ) ) )
       
   424     {
       
   425       FreeDosObject( DOS_FIB, fib );
       
   426       Close ( sysfile->file );
       
   427       FreeMem ( sysfile, sizeof ( struct SysFile ));
       
   428       FT_ERROR(( "FT_Stream_Open:" ));
       
   429       FT_ERROR(( " could not open `%s'\n", filepathname ));
       
   430 
       
   431       return FT_Err_Cannot_Open_Resource;
       
   432     }
       
   433     stream->size = fib->fib_Size;
       
   434     FreeDosObject( DOS_FIB, fib );
       
   435 
       
   436     stream->descriptor.pointer = (void *)sysfile;
       
   437     stream->pathname.pointer   = (char*)filepathname;
       
   438     sysfile->iobuf_start       = 0;
       
   439     sysfile->iobuf_end         = 0;
       
   440     stream->pos                = 0;
       
   441 
       
   442     stream->read  = ft_amiga_stream_io;
       
   443     stream->close = ft_amiga_stream_close;
       
   444 
       
   445     if ( !stream->size )
       
   446     {
       
   447       ft_amiga_stream_close( stream );
       
   448       FT_ERROR(( "FT_Stream_Open:" ));
       
   449       FT_ERROR(( " opened `%s' but zero-sized\n", filepathname ));
       
   450       return FT_Err_Cannot_Open_Stream;;
       
   451     }
       
   452 
       
   453     FT_TRACE1(( "FT_Stream_Open:" ));
       
   454     FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
       
   455                 filepathname, stream->size ));
       
   456 
       
   457     return FT_Err_Ok;
       
   458   }
       
   459 
       
   460 
       
   461 #ifdef FT_DEBUG_MEMORY
       
   462 
       
   463   extern FT_Int
       
   464   ft_mem_debug_init( FT_Memory  memory );
       
   465 
       
   466   extern void
       
   467   ft_mem_debug_done( FT_Memory  memory );
       
   468 
       
   469 #endif
       
   470 
       
   471 
       
   472   /* documentation is in ftobjs.h */
       
   473 
       
   474   FT_BASE_DEF( FT_Memory )
       
   475   FT_New_Memory( void )
       
   476   {
       
   477     FT_Memory  memory;
       
   478 
       
   479 
       
   480 #ifdef __amigaos4__
       
   481     memory = (FT_Memory)AllocVec( sizeof ( *memory ), MEMF_SHARED );
       
   482 #else
       
   483     memory = (FT_Memory)AllocVec( sizeof ( *memory ), MEMF_PUBLIC );
       
   484 #endif
       
   485     if ( memory )
       
   486     {
       
   487 #ifdef __amigaos4__
       
   488       memory->user = CreatePool( MEMF_SHARED, 16384, 16384 );
       
   489 #else
       
   490       memory->user = CreatePool( MEMF_PUBLIC, 16384, 16384 );
       
   491 #endif
       
   492       if ( memory->user == NULL )
       
   493       {
       
   494         FreeVec( memory );
       
   495         memory = NULL;
       
   496       }
       
   497       else
       
   498       {
       
   499         memory->alloc   = ft_alloc;
       
   500         memory->realloc = ft_realloc;
       
   501         memory->free    = ft_free;
       
   502 #ifdef FT_DEBUG_MEMORY
       
   503         ft_mem_debug_init( memory );
       
   504 #endif
       
   505       }
       
   506     }
       
   507 
       
   508     return memory;
       
   509   }
       
   510 
       
   511 
       
   512   /* documentation is in ftobjs.h */
       
   513 
       
   514   FT_BASE_DEF( void )
       
   515   FT_Done_Memory( FT_Memory  memory )
       
   516   {
       
   517 #ifdef FT_DEBUG_MEMORY
       
   518     ft_mem_debug_done( memory );
       
   519 #endif
       
   520 
       
   521     DeletePool( memory->user );
       
   522     FreeVec( memory );
       
   523   }
       
   524 
       
   525 /*
       
   526 Local Variables:
       
   527 coding: latin-1
       
   528 End:
       
   529 */
       
   530 /* END */