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
);