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 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
Alloc_VecPooled(APTR poolHeader,ULONG memSize)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
Free_VecPooled(APTR poolHeader,APTR memory)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* )
ft_alloc(FT_Memory memory,long size)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* )
ft_realloc(FT_Memory memory,long cur_size,long new_size,void * block)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 )
ft_free(FT_Memory memory,void * block)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 )
ft_amiga_stream_close(FT_Stream stream)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 )
ft_amiga_stream_io(FT_Stream stream,unsigned long offset,unsigned char * buffer,unsigned long count)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 )
FT_Stream_Open(FT_Stream stream,const char * filepathname)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 )
FT_New_Memory(void)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 )
FT_Done_Memory(FT_Memory memory)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