1 /***************************************************************************/
5 /* I/O stream support (body). */
7 /* Copyright 2000-2001 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 /***************************************************************************/
20 #include FT_INTERNAL_STREAM_H
21 #include FT_INTERNAL_DEBUG_H
24 /*************************************************************************/
26 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
27 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
28 /* messages during execution. */
31 #define FT_COMPONENT trace_stream
35 FT_New_Memory_Stream( FT_Library library,
40 stream->memory = library->memory;
50 FT_BASE_DEF( FT_Error )
51 FT_Seek_Stream( FT_Stream stream,
61 if ( stream->read( stream, pos, 0, 0 ) )
63 FT_ERROR(( "FT_Seek_Stream:" ));
64 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
67 error = FT_Err_Invalid_Stream_Operation;
72 /* note that seeking to the first position after the file is valid */
73 else if ( pos > stream->size )
75 FT_ERROR(( "FT_Seek_Stream:" ));
76 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
79 error = FT_Err_Invalid_Stream_Operation;
89 FT_BASE_DEF( FT_Error )
90 FT_Skip_Stream( FT_Stream stream,
93 return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) );
97 FT_BASE_DEF( FT_Long )
98 FT_Stream_Pos( FT_Stream stream )
104 FT_BASE_DEF( FT_Error )
105 FT_Read_Stream( FT_Stream stream,
109 return FT_Read_Stream_At( stream, stream->pos, buffer, count );
113 FT_BASE_DEF( FT_Error )
114 FT_Read_Stream_At( FT_Stream stream,
119 FT_Error error = FT_Err_Ok;
123 if ( pos >= stream->size )
125 FT_ERROR(( "FT_Read_Stream_At:" ));
126 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
127 pos, stream->size ));
129 return FT_Err_Invalid_Stream_Operation;
133 read_bytes = stream->read( stream, pos, buffer, count );
136 read_bytes = stream->size - pos;
137 if ( read_bytes > count )
140 MEM_Copy( buffer, stream->base + pos, read_bytes );
143 stream->pos = pos + read_bytes;
145 if ( read_bytes < count )
147 FT_ERROR(( "FT_Read_Stream_At:" ));
148 FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
149 count, read_bytes ));
151 error = FT_Err_Invalid_Stream_Operation;
158 FT_BASE_DEF( FT_Error )
159 FT_Extract_Frame( FT_Stream stream,
166 error = FT_Access_Frame( stream, count );
169 *pbytes = (FT_Byte*)stream->cursor;
171 /* equivalent to FT_Forget_Frame(), with no memory block release */
181 FT_Release_Frame( FT_Stream stream,
186 FT_Memory memory = stream->memory;
195 FT_BASE_DEF( FT_Error )
196 FT_Access_Frame( FT_Stream stream,
199 FT_Error error = FT_Err_Ok;
203 /* check for nested frame access */
204 FT_Assert( stream && stream->cursor == 0 );
208 /* allocate the frame in memory */
209 FT_Memory memory = stream->memory;
212 if ( ALLOC( stream->base, count ) )
216 read_bytes = stream->read( stream, stream->pos,
217 stream->base, count );
218 if ( read_bytes < count )
220 FT_ERROR(( "FT_Access_Frame:" ));
221 FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
222 count, read_bytes ));
224 FREE( stream->base );
225 error = FT_Err_Invalid_Stream_Operation;
227 stream->cursor = stream->base;
228 stream->limit = stream->cursor + count;
229 stream->pos += read_bytes;
233 /* check current and new position */
234 if ( stream->pos >= stream->size ||
235 stream->pos + count > stream->size )
237 FT_ERROR(( "FT_Access_Frame:" ));
238 FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
239 stream->pos, count, stream->size ));
241 error = FT_Err_Invalid_Stream_Operation;
246 stream->cursor = stream->base + stream->pos;
247 stream->limit = stream->cursor + count;
248 stream->pos += count;
257 FT_Forget_Frame( FT_Stream stream )
259 /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */
260 /* that it is possible to access a frame of length 0 in */
261 /* some weird fonts (usually, when accessing an array of */
262 /* 0 records, like in some strange kern tables). */
264 /* In this case, the loader code handles the 0-length table */
265 /* gracefully; however, stream.cursor is really set to 0 by the */
266 /* FT_Access_Frame() call, and this is not an error. */
272 FT_Memory memory = stream->memory;
275 FREE( stream->base );
282 FT_BASE_DEF( FT_Char )
283 FT_Get_Char( FT_Stream stream )
288 FT_Assert( stream && stream->cursor );
291 if ( stream->cursor < stream->limit )
292 result = *stream->cursor++;
298 FT_BASE_DEF( FT_Short )
299 FT_Get_Short( FT_Stream stream )
305 FT_Assert( stream && stream->cursor );
309 if ( p + 1 < stream->limit )
310 result = NEXT_Short( p );
317 FT_BASE_DEF( FT_Short )
318 FT_Get_ShortLE( FT_Stream stream )
324 FT_Assert( stream && stream->cursor );
328 if ( p + 1 < stream->limit )
329 result = NEXT_ShortLE( p );
336 FT_BASE_DEF( FT_Long )
337 FT_Get_Offset( FT_Stream stream )
343 FT_Assert( stream && stream->cursor );
347 if ( p + 2 < stream->limit )
348 result = NEXT_Offset( p );
354 FT_BASE_DEF( FT_Long )
355 FT_Get_Long( FT_Stream stream )
361 FT_Assert( stream && stream->cursor );
365 if ( p + 3 < stream->limit )
366 result = NEXT_Long( p );
372 FT_BASE_DEF( FT_Long )
373 FT_Get_LongLE( FT_Stream stream )
379 FT_Assert( stream && stream->cursor );
383 if ( p + 3 < stream->limit )
384 result = NEXT_LongLE( p );
390 FT_BASE_DEF( FT_Char )
391 FT_Read_Char( FT_Stream stream,
403 if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
408 if ( stream->pos < stream->size )
409 result = stream->base[stream->pos];
418 *error = FT_Err_Invalid_Stream_Operation;
419 FT_ERROR(( "FT_Read_Char:" ));
420 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
421 stream->pos, stream->size ));
427 FT_BASE_DEF( FT_Short )
428 FT_Read_Short( FT_Stream stream,
440 if ( stream->pos + 1 < stream->size )
444 if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
451 p = stream->base + stream->pos;
455 result = NEXT_Short( p );
465 *error = FT_Err_Invalid_Stream_Operation;
466 FT_ERROR(( "FT_Read_Short:" ));
467 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
468 stream->pos, stream->size ));
474 FT_BASE_DEF( FT_Short )
475 FT_Read_ShortLE( FT_Stream stream,
487 if ( stream->pos + 1 < stream->size )
491 if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
498 p = stream->base + stream->pos;
502 result = NEXT_ShortLE( p );
512 *error = FT_Err_Invalid_Stream_Operation;
513 FT_ERROR(( "FT_Read_Short:" ));
514 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
515 stream->pos, stream->size ));
521 FT_BASE_DEF( FT_Long )
522 FT_Read_Offset( FT_Stream stream,
534 if ( stream->pos + 2 < stream->size )
538 if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
545 p = stream->base + stream->pos;
549 result = NEXT_Offset( p );
559 *error = FT_Err_Invalid_Stream_Operation;
560 FT_ERROR(( "FT_Read_Offset:" ));
561 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
562 stream->pos, stream->size ));
568 FT_BASE_DEF( FT_Long )
569 FT_Read_Long( FT_Stream stream,
581 if ( stream->pos + 3 < stream->size )
585 if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
592 p = stream->base + stream->pos;
596 result = NEXT_Long( p );
606 FT_ERROR(( "FT_Read_Long:" ));
607 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
608 stream->pos, stream->size ));
609 *error = FT_Err_Invalid_Stream_Operation;
615 FT_BASE_DEF( FT_Long )
616 FT_Read_LongLE( FT_Stream stream,
628 if ( stream->pos + 3 < stream->size )
632 if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
639 p = stream->base + stream->pos;
643 result = NEXT_LongLE( p );
653 FT_ERROR(( "FT_Read_Long:" ));
654 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
655 stream->pos, stream->size ));
656 *error = FT_Err_Invalid_Stream_Operation;
662 FT_BASE_DEF( FT_Error )
663 FT_Read_Fields( FT_Stream stream,
664 const FT_Frame_Field* fields,
668 FT_Bool frame_accessed = 0;
669 FT_Byte* cursor = stream->cursor;
672 if ( !fields || !stream )
673 return FT_Err_Invalid_Argument;
683 switch ( fields->value )
685 case ft_frame_start: /* access a new frame */
686 error = FT_Access_Frame( stream, fields->offset );
691 cursor = stream->cursor;
693 continue; /* loop! */
695 case ft_frame_bytes: /* read a byte sequence */
696 case ft_frame_skip: /* skip some bytes */
698 FT_UInt len = fields->size;
701 if ( cursor + len > stream->limit )
703 error = FT_Err_Invalid_Stream_Operation;
707 if ( fields->value == ft_frame_bytes )
709 p = (FT_Byte*)structure + fields->offset;
710 MEM_Copy( p, cursor, len );
718 case ft_frame_schar: /* read a single byte */
719 value = NEXT_Byte(cursor);
723 case ft_frame_short_be:
724 case ft_frame_ushort_be: /* read a 2-byte big-endian short */
725 value = NEXT_UShort(cursor);
729 case ft_frame_short_le:
730 case ft_frame_ushort_le: /* read a 2-byte little-endian short */
731 value = NEXT_UShortLE(cursor);
735 case ft_frame_long_be:
736 case ft_frame_ulong_be: /* read a 4-byte big-endian long */
737 value = NEXT_ULong(cursor);
741 case ft_frame_long_le:
742 case ft_frame_ulong_le: /* read a 4-byte little-endian long */
743 value = NEXT_ULongLE(cursor);
747 case ft_frame_off3_be:
748 case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
749 value = NEXT_UOffset(cursor);
753 case ft_frame_off3_le:
754 case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
755 value = NEXT_UOffsetLE(cursor);
760 /* otherwise, exit the loop */
761 stream->cursor = cursor;
765 /* now, compute the signed value is necessary */
766 if ( fields->value & FT_FRAME_OP_SIGNED )
767 value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
769 /* finally, store the value in the object */
771 p = (FT_Byte*)structure + fields->offset;
772 switch ( fields->size )
775 *(FT_Byte*)p = (FT_Byte)value;
779 *(FT_UShort*)p = (FT_UShort)value;
783 *(FT_UInt32*)p = (FT_UInt32)value;
786 default: /* for 64-bit systems */
787 *(FT_ULong*)p = (FT_ULong)value;
790 /* go to next field */
796 /* close the frame if it was opened by this read */
797 if ( frame_accessed )
798 FT_Forget_Frame( stream );