Home | History | Annotate | Download | only in base
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftsystem.c                                                             */
      4 /*                                                                         */
      5 /*    Amiga-specific FreeType low-level system interface (body).           */
      6 /*                                                                         */
      7 /*  Copyright 1996-2018 by                                                 */
      8 /*  David Turner, Robert Wilhelm, Werner Lemberg and Detlef Wrkner.       */
      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 Wrkner <TetiSoft (at) 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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 */
    531