1
/***************************************************************************/
5
/* I/O stream support (body). */
7
/* Copyright 2000-2001, 2002, 2004 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_Stream_OpenMemory( FT_Stream stream,
39
stream->base = (FT_Byte*) base;
49
FT_Stream_Close( FT_Stream stream )
51
if ( stream && stream->close )
53
stream->close( stream );
59
FT_BASE_DEF( FT_Error )
60
FT_Stream_Seek( FT_Stream stream,
63
FT_Error error = FT_Err_Ok;
70
if ( stream->read( stream, pos, 0, 0 ) )
72
FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
75
error = FT_Err_Invalid_Stream_Operation;
78
/* note that seeking to the first position after the file is valid */
79
else if ( pos > stream->size )
81
FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
84
error = FT_Err_Invalid_Stream_Operation;
91
FT_BASE_DEF( FT_Error )
92
FT_Stream_Skip( FT_Stream stream,
95
return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
99
FT_BASE_DEF( FT_Long )
100
FT_Stream_Pos( FT_Stream stream )
106
FT_BASE_DEF( FT_Error )
107
FT_Stream_Read( FT_Stream stream,
111
return FT_Stream_ReadAt( stream, stream->pos, buffer, count );
115
FT_BASE_DEF( FT_Error )
116
FT_Stream_ReadAt( FT_Stream stream,
121
FT_Error error = FT_Err_Ok;
125
if ( pos >= stream->size )
127
FT_ERROR(( "FT_Stream_ReadAt: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
128
pos, stream->size ));
130
return FT_Err_Invalid_Stream_Operation;
134
read_bytes = stream->read( stream, pos, buffer, count );
137
read_bytes = stream->size - pos;
138
if ( read_bytes > count )
141
FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
144
stream->pos = pos + read_bytes;
146
if ( read_bytes < count )
148
FT_ERROR(( "FT_Stream_ReadAt:" ));
149
FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
150
count, read_bytes ));
152
error = FT_Err_Invalid_Stream_Operation;
159
FT_BASE_DEF( FT_Error )
160
FT_Stream_ExtractFrame( FT_Stream stream,
167
error = FT_Stream_EnterFrame( stream, count );
170
*pbytes = (FT_Byte*)stream->cursor;
172
/* equivalent to FT_Stream_ExitFrame(), with no memory block release */
182
FT_Stream_ReleaseFrame( FT_Stream stream,
187
FT_Memory memory = stream->memory;
196
FT_BASE_DEF( FT_Error )
197
FT_Stream_EnterFrame( FT_Stream stream,
200
FT_Error error = FT_Err_Ok;
204
/* check for nested frame access */
205
FT_ASSERT( stream && stream->cursor == 0 );
209
/* allocate the frame in memory */
210
FT_Memory memory = stream->memory;
213
if ( FT_QALLOC( stream->base, count ) )
217
read_bytes = stream->read( stream, stream->pos,
218
stream->base, count );
219
if ( read_bytes < count )
221
FT_ERROR(( "FT_Stream_EnterFrame:" ));
222
FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
223
count, read_bytes ));
225
FT_FREE( stream->base );
226
error = FT_Err_Invalid_Stream_Operation;
228
stream->cursor = stream->base;
229
stream->limit = stream->cursor + count;
230
stream->pos += read_bytes;
234
/* check current and new position */
235
if ( stream->pos >= stream->size ||
236
stream->pos + count > stream->size )
238
FT_ERROR(( "FT_Stream_EnterFrame:" ));
239
FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
240
stream->pos, count, stream->size ));
242
error = FT_Err_Invalid_Stream_Operation;
247
stream->cursor = stream->base + stream->pos;
248
stream->limit = stream->cursor + count;
249
stream->pos += count;
258
FT_Stream_ExitFrame( FT_Stream stream )
260
/* IMPORTANT: The assertion stream->cursor != 0 was removed, given */
261
/* that it is possible to access a frame of length 0 in */
262
/* some weird fonts (usually, when accessing an array of */
263
/* 0 records, like in some strange kern tables). */
265
/* In this case, the loader code handles the 0-length table */
266
/* gracefully; however, stream.cursor is really set to 0 by the */
267
/* FT_Stream_EnterFrame() call, and this is not an error. */
273
FT_Memory memory = stream->memory;
276
FT_FREE( stream->base );
283
FT_BASE_DEF( FT_Char )
284
FT_Stream_GetChar( FT_Stream stream )
289
FT_ASSERT( stream && stream->cursor );
292
if ( stream->cursor < stream->limit )
293
result = *stream->cursor++;
299
FT_BASE_DEF( FT_Short )
300
FT_Stream_GetShort( FT_Stream stream )
306
FT_ASSERT( stream && stream->cursor );
310
if ( p + 1 < stream->limit )
311
result = FT_NEXT_SHORT( p );
318
FT_BASE_DEF( FT_Short )
319
FT_Stream_GetShortLE( FT_Stream stream )
325
FT_ASSERT( stream && stream->cursor );
329
if ( p + 1 < stream->limit )
330
result = FT_NEXT_SHORT_LE( p );
337
FT_BASE_DEF( FT_Long )
338
FT_Stream_GetOffset( FT_Stream stream )
344
FT_ASSERT( stream && stream->cursor );
348
if ( p + 2 < stream->limit )
349
result = FT_NEXT_OFF3( p );
355
FT_BASE_DEF( FT_Long )
356
FT_Stream_GetLong( FT_Stream stream )
362
FT_ASSERT( stream && stream->cursor );
366
if ( p + 3 < stream->limit )
367
result = FT_NEXT_LONG( p );
373
FT_BASE_DEF( FT_Long )
374
FT_Stream_GetLongLE( FT_Stream stream )
380
FT_ASSERT( stream && stream->cursor );
384
if ( p + 3 < stream->limit )
385
result = FT_NEXT_LONG_LE( p );
391
FT_BASE_DEF( FT_Char )
392
FT_Stream_ReadChar( FT_Stream stream,
404
if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
409
if ( stream->pos < stream->size )
410
result = stream->base[stream->pos];
419
*error = FT_Err_Invalid_Stream_Operation;
420
FT_ERROR(( "FT_Stream_ReadChar: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
421
stream->pos, stream->size ));
427
FT_BASE_DEF( FT_Short )
428
FT_Stream_ReadShort( 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 = FT_NEXT_SHORT( p );
465
*error = FT_Err_Invalid_Stream_Operation;
466
FT_ERROR(( "FT_Stream_ReadShort:" ));
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_Stream_ReadShortLE( 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 = FT_NEXT_SHORT_LE( p );
512
*error = FT_Err_Invalid_Stream_Operation;
513
FT_ERROR(( "FT_Stream_ReadShortLE:" ));
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_Stream_ReadOffset( 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 = FT_NEXT_OFF3( p );
559
*error = FT_Err_Invalid_Stream_Operation;
560
FT_ERROR(( "FT_Stream_ReadOffset:" ));
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_Stream_ReadLong( 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 = FT_NEXT_LONG( p );
606
FT_ERROR(( "FT_Stream_ReadLong: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
607
stream->pos, stream->size ));
608
*error = FT_Err_Invalid_Stream_Operation;
614
FT_BASE_DEF( FT_Long )
615
FT_Stream_ReadLongLE( FT_Stream stream,
627
if ( stream->pos + 3 < stream->size )
631
if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
638
p = stream->base + stream->pos;
642
result = FT_NEXT_LONG_LE( p );
652
FT_ERROR(( "FT_Stream_ReadLongLE:" ));
653
FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
654
stream->pos, stream->size ));
655
*error = FT_Err_Invalid_Stream_Operation;
661
FT_BASE_DEF( FT_Error )
662
FT_Stream_ReadFields( FT_Stream stream,
663
const FT_Frame_Field* fields,
667
FT_Bool frame_accessed = 0;
668
FT_Byte* cursor = stream->cursor;
671
if ( !fields || !stream )
672
return FT_Err_Invalid_Argument;
682
switch ( fields->value )
684
case ft_frame_start: /* access a new frame */
685
error = FT_Stream_EnterFrame( stream, fields->offset );
690
cursor = stream->cursor;
692
continue; /* loop! */
694
case ft_frame_bytes: /* read a byte sequence */
695
case ft_frame_skip: /* skip some bytes */
697
FT_UInt len = fields->size;
700
if ( cursor + len > stream->limit )
702
error = FT_Err_Invalid_Stream_Operation;
706
if ( fields->value == ft_frame_bytes )
708
p = (FT_Byte*)structure + fields->offset;
709
FT_MEM_COPY( p, cursor, len );
717
case ft_frame_schar: /* read a single byte */
718
value = FT_NEXT_BYTE(cursor);
722
case ft_frame_short_be:
723
case ft_frame_ushort_be: /* read a 2-byte big-endian short */
724
value = FT_NEXT_USHORT(cursor);
728
case ft_frame_short_le:
729
case ft_frame_ushort_le: /* read a 2-byte little-endian short */
730
value = FT_NEXT_USHORT_LE(cursor);
734
case ft_frame_long_be:
735
case ft_frame_ulong_be: /* read a 4-byte big-endian long */
736
value = FT_NEXT_ULONG(cursor);
740
case ft_frame_long_le:
741
case ft_frame_ulong_le: /* read a 4-byte little-endian long */
742
value = FT_NEXT_ULONG_LE(cursor);
746
case ft_frame_off3_be:
747
case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
748
value = FT_NEXT_UOFF3(cursor);
752
case ft_frame_off3_le:
753
case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
754
value = FT_NEXT_UOFF3_LE(cursor);
759
/* otherwise, exit the loop */
760
stream->cursor = cursor;
764
/* now, compute the signed value is necessary */
765
if ( fields->value & FT_FRAME_OP_SIGNED )
766
value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
768
/* finally, store the value in the object */
770
p = (FT_Byte*)structure + fields->offset;
771
switch ( fields->size )
773
case (8 / FT_CHAR_BIT):
774
*(FT_Byte*)p = (FT_Byte)value;
777
case (16 / FT_CHAR_BIT):
778
*(FT_UShort*)p = (FT_UShort)value;
781
case (32 / FT_CHAR_BIT):
782
*(FT_UInt32*)p = (FT_UInt32)value;
785
default: /* for 64-bit systems */
786
*(FT_ULong*)p = (FT_ULong)value;
789
/* go to next field */
795
/* close the frame if it was opened by this read */
796
if ( frame_accessed )
797
FT_Stream_ExitFrame( stream );