1 /***************************************************************************/
5 /* Amiga-specific FreeType low-level system interface (body). */
7 /* Copyright 1996-2001, 2002, 2005, 2006, 2007, 2010 by */
8 /* David Turner, Robert Wilhelm, Werner Lemberg and Detlef Würkner. */
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. */
16 /***************************************************************************/
18 /*************************************************************************/
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. */
24 /*************************************************************************/
27 /*************************************************************************/
29 /* Maintained by Detlef Würkner <TetiSoft@apg.lahn.de> */
31 /* Based on the original ftsystem.c, */
32 /* modified to avoid fopen(), fclose(), fread(), fseek(), ftell(), */
33 /* malloc(), realloc(), and free(). */
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 */
40 /* This implementation needs exec V39+ because it uses AllocPooled() etc */
42 /*************************************************************************/
45 #define __NOGLOBALIFACE__
46 #define __USE_INLINE__
47 #include <proto/exec.h>
48 #include <dos/stdio.h>
49 #include <proto/dos.h>
51 extern struct ExecIFace *IExec;
52 extern struct DOSIFace *IDOS;
54 extern struct Library *SysBase;
55 extern struct Library *DOSBase;
58 #define IOBUF_SIZE 512
60 /* structure that helps us to avoid
61 * useless calls of Seek() and Read()
68 UBYTE iobuf[IOBUF_SIZE];
72 /* C implementation of AllocVecPooled (see autodoc exec/AllocPooled) */
74 Alloc_VecPooled( APTR poolHeader,
77 ULONG newSize = memSize + sizeof ( ULONG );
78 ULONG *mem = AllocPooled( poolHeader, newSize );
86 /* C implementation of FreeVecPooled (see autodoc exec/AllocPooled) */
88 Free_VecPooled( APTR poolHeader,
91 ULONG *realmem = (ULONG *)memory - 1;
93 FreePooled( poolHeader, realmem, *realmem );
98 #include FT_CONFIG_CONFIG_H
99 #include FT_INTERNAL_DEBUG_H
109 /*************************************************************************/
111 /* MEMORY MANAGEMENT INTERFACE */
113 /*************************************************************************/
115 /*************************************************************************/
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(). */
121 /*************************************************************************/
124 /*************************************************************************/
130 /* The memory allocation function. */
133 /* memory :: A pointer to the memory object. */
135 /* size :: The requested size in bytes. */
138 /* The address of newly allocated block. */
140 FT_CALLBACK_DEF( void* )
141 ft_alloc( FT_Memory memory,
145 return AllocVecPooled( memory->user, size );
147 return Alloc_VecPooled( memory->user, size );
152 /*************************************************************************/
158 /* The memory reallocation function. */
161 /* memory :: A pointer to the memory object. */
163 /* cur_size :: The current size of the allocated memory block. */
165 /* new_size :: The newly requested size in bytes. */
167 /* block :: The current address of the block in memory. */
170 /* The address of the reallocated memory block. */
172 FT_CALLBACK_DEF( void* )
173 ft_realloc( FT_Memory memory,
181 new_block = AllocVecPooled ( memory->user, new_size );
183 new_block = Alloc_VecPooled ( memory->user, new_size );
185 if ( new_block != NULL )
187 CopyMem ( block, new_block,
188 ( new_size > cur_size ) ? cur_size : new_size );
190 FreeVecPooled ( memory->user, block );
192 Free_VecPooled ( memory->user, block );
199 /*************************************************************************/
205 /* The memory release function. */
208 /* memory :: A pointer to the memory object. */
210 /* block :: The address of block in memory to be freed. */
212 FT_CALLBACK_DEF( void )
213 ft_free( FT_Memory memory,
217 FreeVecPooled( memory->user, block );
219 Free_VecPooled( memory->user, block );
224 /*************************************************************************/
226 /* RESOURCE MANAGEMENT INTERFACE */
228 /*************************************************************************/
231 /*************************************************************************/
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. */
238 #define FT_COMPONENT trace_io
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 )
245 /*************************************************************************/
248 /* ft_amiga_stream_close */
251 /* The function to close a stream. */
254 /* stream :: A pointer to the stream object. */
256 FT_CALLBACK_DEF( void )
257 ft_amiga_stream_close( FT_Stream stream )
259 struct SysFile* sysfile;
261 sysfile = STREAM_FILE( stream );
262 Close ( sysfile->file );
263 FreeMem ( sysfile, sizeof ( struct SysFile ));
265 stream->descriptor.pointer = NULL;
271 /*************************************************************************/
274 /* ft_amiga_stream_io */
277 /* The function to open a stream. */
280 /* stream :: A pointer to the stream object. */
282 /* offset :: The position in the data stream to start reading. */
284 /* buffer :: The address of buffer to store the read data. */
286 /* count :: The number of bytes to read from the stream. */
289 /* The number of bytes actually read. */
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 )
297 struct SysFile* sysfile;
298 unsigned long read_bytes;
302 sysfile = STREAM_FILE( stream );
304 /* handle the seek */
305 if ( (offset < sysfile->iobuf_start) || (offset + count > sysfile->iobuf_end) )
307 /* requested offset implies we need a buffer refill */
308 if ( !sysfile->iobuf_end || offset != sysfile->iobuf_end )
310 /* a physical seek is necessary */
311 Seek( sysfile->file, offset, OFFSET_BEGINNING );
313 sysfile->iobuf_start = offset;
314 sysfile->iobuf_end = 0; /* trigger a buffer refill */
317 /* handle the read */
318 if ( offset + count <= sysfile->iobuf_end )
320 /* we have buffer and requested bytes are all inside our buffer */
321 CopyMem( &sysfile->iobuf[offset - sysfile->iobuf_start], buffer, count );
326 /* (re)fill buffer */
327 if ( count <= IOBUF_SIZE )
329 /* requested bytes is a subset of the buffer */
330 read_bytes = Read( sysfile->file, sysfile->iobuf, IOBUF_SIZE );
331 if ( read_bytes == -1UL )
338 sysfile->iobuf_end = offset + read_bytes;
339 CopyMem( sysfile->iobuf, buffer, count );
340 if ( read_bytes > count )
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 )
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 );
378 /* documentation is in ftobjs.h */
380 FT_BASE_DEF( FT_Error )
381 FT_Stream_Open( FT_Stream stream,
382 const char* filepathname )
384 struct FileInfoBlock* fib;
385 struct SysFile* sysfile;
389 return FT_Err_Invalid_Stream_Handle;
392 sysfile = AllocMem ( sizeof (struct SysFile ), MEMF_SHARED );
394 sysfile = AllocMem ( sizeof (struct SysFile ), MEMF_PUBLIC );
398 FT_ERROR(( "FT_Stream_Open:" ));
399 FT_ERROR(( " could not open `%s'\n", filepathname ));
401 return FT_Err_Cannot_Open_Resource;
403 sysfile->file = Open( (STRPTR)filepathname, MODE_OLDFILE );
404 if ( !sysfile->file )
406 FreeMem ( sysfile, sizeof ( struct SysFile ));
407 FT_ERROR(( "FT_Stream_Open:" ));
408 FT_ERROR(( " could not open `%s'\n", filepathname ));
410 return FT_Err_Cannot_Open_Resource;
413 fib = AllocDosObject( DOS_FIB, NULL );
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 ));
421 return FT_Err_Cannot_Open_Resource;
423 if ( !( ExamineFH( sysfile->file, fib ) ) )
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 ));
431 return FT_Err_Cannot_Open_Resource;
433 stream->size = fib->fib_Size;
434 FreeDosObject( DOS_FIB, fib );
436 stream->descriptor.pointer = (void *)sysfile;
437 stream->pathname.pointer = (char*)filepathname;
438 sysfile->iobuf_start = 0;
439 sysfile->iobuf_end = 0;
442 stream->read = ft_amiga_stream_io;
443 stream->close = ft_amiga_stream_close;
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;;
453 FT_TRACE1(( "FT_Stream_Open:" ));
454 FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
455 filepathname, stream->size ));
461 #ifdef FT_DEBUG_MEMORY
464 ft_mem_debug_init( FT_Memory memory );
467 ft_mem_debug_done( FT_Memory memory );
472 /* documentation is in ftobjs.h */
474 FT_BASE_DEF( FT_Memory )
475 FT_New_Memory( void )
481 memory = (FT_Memory)AllocVec( sizeof ( *memory ), MEMF_SHARED );
483 memory = (FT_Memory)AllocVec( sizeof ( *memory ), MEMF_PUBLIC );
488 memory->user = CreatePool( MEMF_SHARED, 16384, 16384 );
490 memory->user = CreatePool( MEMF_PUBLIC, 16384, 16384 );
492 if ( memory->user == NULL )
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 );
512 /* documentation is in ftobjs.h */
515 FT_Done_Memory( FT_Memory memory )
517 #ifdef FT_DEBUG_MEMORY
518 ft_mem_debug_done( memory );
521 DeletePool( memory->user );