1 /***************************************************************************/
5 /* I/O stream support (body). */
7 /* Copyright 2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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 /***************************************************************************/
19 #include <freetype/internal/ftstream.h>
20 #include <freetype/internal/ftdebug.h>
23 /*************************************************************************/
25 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
26 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
27 /* messages during execution. */
30 #define FT_COMPONENT trace_stream
33 BASE_FUNC( void ) FT_New_Memory_Stream( FT_Library library,
38 stream->memory = library->memory;
48 BASE_FUNC( FT_Error ) FT_Seek_Stream( FT_Stream stream,
58 if ( stream->read( stream, pos, 0, 0 ) )
60 FT_ERROR(( "FT_Seek_Stream:" ));
61 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
64 error = FT_Err_Invalid_Stream_Operation;
69 /* note that seeking to the first position after the file is valid */
70 else if ( pos > stream->size )
72 FT_ERROR(( "FT_Seek_Stream:" ));
73 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
76 error = FT_Err_Invalid_Stream_Operation;
86 BASE_FUNC( FT_Error ) FT_Skip_Stream( FT_Stream stream,
89 return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) );
93 BASE_FUNC( FT_Long ) FT_Stream_Pos( FT_Stream stream )
99 BASE_FUNC( FT_Error ) FT_Read_Stream( FT_Stream stream,
103 return FT_Read_Stream_At( stream, stream->pos, buffer, count );
107 BASE_FUNC( FT_Error ) FT_Read_Stream_At( FT_Stream stream,
112 FT_Error error = FT_Err_Ok;
116 if ( pos >= stream->size )
118 FT_ERROR(( "FT_Read_Stream_At:" ));
119 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
120 pos, stream->size ));
122 return FT_Err_Invalid_Stream_Operation;
126 read_bytes = stream->read( stream, pos, buffer, count );
129 read_bytes = stream->size - pos;
130 if ( read_bytes > count )
133 MEM_Copy( buffer, stream->base + pos, read_bytes );
136 stream->pos = pos + read_bytes;
138 if ( read_bytes < count )
140 FT_ERROR(( "FT_Read_Stream_At:" ));
141 FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
142 count, read_bytes ));
144 error = FT_Err_Invalid_Stream_Operation;
151 BASE_FUNC( FT_Error ) FT_Extract_Frame( FT_Stream stream,
158 error = FT_Access_Frame( stream, count );
161 *pbytes = (FT_Byte*)stream->cursor;
163 /* equivalent to FT_Forget_Frame(), with no memory block release */
172 BASE_FUNC( void ) FT_Release_Frame( FT_Stream stream,
177 FT_Memory memory = stream->memory;
186 BASE_FUNC( FT_Error ) FT_Access_Frame( FT_Stream stream,
189 FT_Error error = FT_Err_Ok;
193 /* check for nested frame access */
194 FT_Assert( stream && stream->cursor == 0 );
198 /* allocate the frame in memory */
199 FT_Memory memory = stream->memory;
202 if ( ALLOC( stream->base, count ) )
206 read_bytes = stream->read( stream, stream->pos,
207 stream->base, count );
208 if ( read_bytes < count )
210 FT_ERROR(( "FT_Access_Frame:" ));
211 FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
212 count, read_bytes ));
214 FREE( stream->base );
215 error = FT_Err_Invalid_Stream_Operation;
217 stream->cursor = stream->base;
218 stream->limit = stream->cursor + count;
219 stream->pos += read_bytes;
223 /* check current and new position */
224 if ( stream->pos >= stream->size ||
225 stream->pos + count > stream->size )
227 FT_ERROR(( "FT_Access_Frame:" ));
228 FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
229 stream->pos, count, stream->size ));
231 error = FT_Err_Invalid_Stream_Operation;
236 stream->cursor = stream->base + stream->pos;
237 stream->limit = stream->cursor + count;
238 stream->pos += count;
246 BASE_FUNC( void ) FT_Forget_Frame( FT_Stream stream )
248 /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */
249 /* that it is possible to access a frame of length 0 in */
250 /* some weird fonts (usually, when accessing an array of */
251 /* 0 records, like in some strange kern tables). */
253 /* In this case, the loader code handles the 0-length table */
254 /* gracefully; however, stream.cursor is really set to 0 by the */
255 /* FT_Access_Frame() call, and this is not an error. */
261 FT_Memory memory = stream->memory;
264 FREE( stream->base );
271 BASE_FUNC( FT_Char ) FT_Get_Char( FT_Stream stream )
276 FT_Assert( stream && stream->cursor );
279 if ( stream->cursor < stream->limit )
280 result = *stream->cursor++;
286 BASE_FUNC( FT_Short ) FT_Get_Short( FT_Stream stream )
292 FT_Assert( stream && stream->cursor );
296 if ( p + 1 < stream->limit )
297 result = NEXT_Short( p );
304 BASE_FUNC( FT_Short ) FT_Get_ShortLE( FT_Stream stream )
310 FT_Assert( stream && stream->cursor );
314 if ( p + 1 < stream->limit )
315 result = NEXT_ShortLE( p );
322 BASE_FUNC( FT_Long ) FT_Get_Offset( FT_Stream stream )
328 FT_Assert( stream && stream->cursor );
332 if ( p + 2 < stream->limit )
333 result = NEXT_Offset( p );
339 BASE_FUNC( FT_Long ) FT_Get_Long( FT_Stream stream )
345 FT_Assert( stream && stream->cursor );
349 if ( p + 3 < stream->limit )
350 result = NEXT_Long( p );
356 BASE_FUNC( FT_Long ) FT_Get_LongLE( FT_Stream stream )
362 FT_Assert( stream && stream->cursor );
366 if ( p + 3 < stream->limit )
367 result = NEXT_LongLE( p );
373 BASE_FUNC( FT_Char ) FT_Read_Char( FT_Stream stream,
385 if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
390 if ( stream->pos < stream->size )
391 result = stream->base[stream->pos];
400 *error = FT_Err_Invalid_Stream_Operation;
401 FT_ERROR(( "FT_Read_Char:" ));
402 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
403 stream->pos, stream->size ));
409 BASE_FUNC( FT_Short ) FT_Read_Short( FT_Stream stream,
421 if ( stream->pos + 1 < stream->size )
425 if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
432 p = stream->base + stream->pos;
436 result = NEXT_Short( p );
446 *error = FT_Err_Invalid_Stream_Operation;
447 FT_ERROR(( "FT_Read_Short:" ));
448 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
449 stream->pos, stream->size ));
455 BASE_FUNC( FT_Short ) FT_Read_ShortLE( FT_Stream stream,
467 if ( stream->pos + 1 < stream->size )
471 if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
478 p = stream->base + stream->pos;
482 result = NEXT_ShortLE( p );
492 *error = FT_Err_Invalid_Stream_Operation;
493 FT_ERROR(( "FT_Read_Short:" ));
494 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
495 stream->pos, stream->size ));
501 BASE_FUNC( FT_Long ) FT_Read_Offset( FT_Stream stream,
513 if ( stream->pos + 2 < stream->size )
517 if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
524 p = stream->base + stream->pos;
528 result = NEXT_Offset( p );
538 *error = FT_Err_Invalid_Stream_Operation;
539 FT_ERROR(( "FT_Read_Offset:" ));
540 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
541 stream->pos, stream->size ));
547 BASE_FUNC( FT_Long ) FT_Read_Long( FT_Stream stream,
559 if ( stream->pos + 3 < stream->size )
563 if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
570 p = stream->base + stream->pos;
574 result = NEXT_Long( p );
584 FT_ERROR(( "FT_Read_Long:" ));
585 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
586 stream->pos, stream->size ));
587 *error = FT_Err_Invalid_Stream_Operation;
593 BASE_FUNC( FT_Long ) FT_Read_LongLE( FT_Stream stream,
605 if ( stream->pos + 3 < stream->size )
609 if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
616 p = stream->base + stream->pos;
620 result = NEXT_LongLE( p );
630 FT_ERROR(( "FT_Read_Long:" ));
631 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
632 stream->pos, stream->size ));
633 *error = FT_Err_Invalid_Stream_Operation;
639 BASE_FUNC( FT_Error ) FT_Read_Fields( FT_Stream stream,
640 const FT_Frame_Field* fields,
644 FT_Bool frame_accessed = 0;
647 if ( !fields || !stream )
648 return FT_Err_Invalid_Argument;
658 switch ( fields->value )
660 case ft_frame_start: /* access a new frame */
661 error = FT_Access_Frame( stream, fields->offset );
667 continue; /* loop! */
669 case ft_frame_bytes: /* read a byte sequence */
670 case ft_frame_skip: /* skip some bytes */
672 FT_Int len = fields->size;
675 if ( stream->cursor + len > stream->limit )
677 error = FT_Err_Invalid_Stream_Operation;
681 if ( fields->value == ft_frame_bytes )
683 p = (FT_Byte*)structure + fields->offset;
684 MEM_Copy( p, stream->cursor, len );
686 stream->cursor += len;
692 case ft_frame_schar: /* read a single byte */
697 case ft_frame_short_be:
698 case ft_frame_ushort_be: /* read a 2-byte big-endian short */
699 value = GET_UShort();
703 case ft_frame_short_le:
704 case ft_frame_ushort_le: /* read a 2-byte little-endian short */
712 if ( p + 1 < stream->limit )
714 value = ( FT_UShort)p[0] | ((FT_UShort)p[1] << 8 );
721 case ft_frame_long_be:
722 case ft_frame_ulong_be: /* read a 4-byte big-endian long */
727 case ft_frame_long_le:
728 case ft_frame_ulong_le: /* read a 4-byte little-endian long */
736 if ( p + 3 < stream->limit )
738 value = (FT_ULong)p[0] |
739 ( (FT_ULong)p[1] << 8 ) |
740 ( (FT_ULong)p[2] << 16 ) |
741 ( (FT_ULong)p[3] << 24 );
748 case ft_frame_off3_be:
749 case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
750 value = GET_UOffset();
754 case ft_frame_off3_le:
755 case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
763 if ( p + 2 < stream->limit )
765 value = (FT_ULong)p[0] |
766 ( (FT_ULong)p[1] << 8 ) |
767 ( (FT_ULong)p[2] << 16 );
775 /* otherwise, exit the loop */
779 /* now, compute the signed value is necessary */
780 if ( fields->value & FT_FRAME_OP_SIGNED )
781 value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
783 /* finally, store the value in the object */
785 p = (FT_Byte*)structure + fields->offset;
786 switch ( fields->size )
789 *(FT_Byte*)p = (FT_Byte)value;
793 *(FT_UShort*)p = (FT_UShort)value;
797 *(FT_UInt32*)p = (FT_UInt32)value;
800 default: /* for 64-bit systems */
801 *(FT_ULong*)p = (FT_ULong)value;
804 /* go to next field */
810 /* close the frame if it was opened by this read */
811 if ( frame_accessed )
812 FT_Forget_Frame( stream );