Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftsystem.c                                                             */
  4. /*                                                                         */
  5. /*    Amiga-specific FreeType low-level system interface (body).           */
  6. /*                                                                         */
  7. /*  Copyright 1996-2002, 2005-2007, 2010, 2013 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_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.