]> git.saurik.com Git - wxWidgets.git/blame - src/freetype/base/ftstream.c
fixed typo that caused incorrect if there was only one book
[wxWidgets.git] / src / freetype / base / ftstream.c
CommitLineData
cabec872
RR
1/***************************************************************************/
2/* */
3/* ftstream.c */
4/* */
5/* I/O stream support (body). */
6/* */
7/* Copyright 2000 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
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#include <freetype/internal/ftstream.h>
20#include <freetype/internal/ftdebug.h>
21
22
23 /*************************************************************************/
24 /* */
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. */
28 /* */
29#undef FT_COMPONENT
30#define FT_COMPONENT trace_stream
31
32
33 BASE_FUNC( void ) FT_New_Memory_Stream( FT_Library library,
34 FT_Byte* base,
35 FT_ULong size,
36 FT_Stream stream )
37 {
38 stream->memory = library->memory;
39 stream->base = base;
40 stream->size = size;
41 stream->pos = 0;
42 stream->cursor = 0;
43 stream->read = 0;
44 stream->close = 0;
45 }
46
47
48 BASE_FUNC( FT_Error ) FT_Seek_Stream( FT_Stream stream,
49 FT_ULong pos )
50 {
51 FT_Error error;
52
53
54 stream->pos = pos;
55
56 if ( stream->read )
57 {
58 if ( stream->read( stream, pos, 0, 0 ) )
59 {
60 FT_ERROR(( "FT_Seek_Stream:" ));
61 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
62 pos, stream->size ));
63
64 error = FT_Err_Invalid_Stream_Operation;
65 }
66 else
67 error = FT_Err_Ok;
68 }
69 /* note that seeking to the first position after the file is valid */
70 else if ( pos > stream->size )
71 {
72 FT_ERROR(( "FT_Seek_Stream:" ));
73 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
74 pos, stream->size ));
75
76 error = FT_Err_Invalid_Stream_Operation;
77 }
78
79 else
80 error = FT_Err_Ok;
81
82 return error;
83 }
84
85
86 BASE_FUNC( FT_Error ) FT_Skip_Stream( FT_Stream stream,
87 FT_Long distance )
88 {
89 return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) );
90 }
91
92
93 BASE_FUNC( FT_Long ) FT_Stream_Pos( FT_Stream stream )
94 {
95 return stream->pos;
96 }
97
98
99 BASE_FUNC( FT_Error ) FT_Read_Stream( FT_Stream stream,
100 FT_Byte* buffer,
101 FT_ULong count )
102 {
103 return FT_Read_Stream_At( stream, stream->pos, buffer, count );
104 }
105
106
107 BASE_FUNC( FT_Error ) FT_Read_Stream_At( FT_Stream stream,
108 FT_ULong pos,
109 FT_Byte* buffer,
110 FT_ULong count )
111 {
112 FT_Error error = FT_Err_Ok;
113 FT_ULong read_bytes;
114
115
116 if ( pos >= stream->size )
117 {
118 FT_ERROR(( "FT_Read_Stream_At:" ));
119 FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
120 pos, stream->size ));
121
122 return FT_Err_Invalid_Stream_Operation;
123 }
124
125 if ( stream->read )
126 read_bytes = stream->read( stream, pos, buffer, count );
127 else
128 {
129 read_bytes = stream->size - pos;
130 if ( read_bytes > count )
131 read_bytes = count;
132
133 MEM_Copy( buffer, stream->base + pos, read_bytes );
134 }
135
136 stream->pos = pos + read_bytes;
137
138 if ( read_bytes < count )
139 {
140 FT_ERROR(( "FT_Read_Stream_At:" ));
141 FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
142 count, read_bytes ));
143
144 error = FT_Err_Invalid_Stream_Operation;
145 }
146
147 return error;
148 }
149
150
151 BASE_FUNC( FT_Error ) FT_Extract_Frame( FT_Stream stream,
152 FT_ULong count,
153 FT_Byte** pbytes )
154 {
155 FT_Error error;
156
157
158 error = FT_Access_Frame( stream, count );
159 if ( !error )
160 {
161 *pbytes = (FT_Byte*)stream->cursor;
162
163 /* equivalent to FT_Forget_Frame(), with no memory block release */
164 stream->cursor = 0;
165 stream->limit = 0;
166 }
167
168 return error;
169 }
170
171
172 BASE_FUNC( void ) FT_Release_Frame( FT_Stream stream,
173 FT_Byte** pbytes )
174 {
175 if ( stream->read )
176 {
177 FT_Memory memory = stream->memory;
178
179
180 FREE( *pbytes );
181 }
182 *pbytes = 0;
183 }
184
185
186 BASE_FUNC( FT_Error ) FT_Access_Frame( FT_Stream stream,
187 FT_ULong count )
188 {
189 FT_Error error = FT_Err_Ok;
190 FT_ULong read_bytes;
191
192
193 /* check for nested frame access */
194 FT_Assert( stream && stream->cursor == 0 );
195
196 if ( stream->read )
197 {
198 /* allocate the frame in memory */
199 FT_Memory memory = stream->memory;
200
201
202 if ( ALLOC( stream->base, count ) )
203 goto Exit;
204
205 /* read it */
206 read_bytes = stream->read( stream, stream->pos,
207 stream->base, count );
208 if ( read_bytes < count )
209 {
210 FT_ERROR(( "FT_Access_Frame:" ));
211 FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
212 count, read_bytes ));
213
214 FREE( stream->base );
215 error = FT_Err_Invalid_Stream_Operation;
216 }
217 stream->cursor = stream->base;
218 stream->limit = stream->cursor + count;
219 stream->pos += read_bytes;
220 }
221 else
222 {
223 /* check current and new position */
224 if ( stream->pos >= stream->size ||
225 stream->pos + count > stream->size )
226 {
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 ));
230
231 error = FT_Err_Invalid_Stream_Operation;
232 goto Exit;
233 }
234
235 /* set cursor */
236 stream->cursor = stream->base + stream->pos;
237 stream->limit = stream->cursor + count;
238 stream->pos += count;
239 }
240
241 Exit:
242 return error;
243 }
244
245
246 BASE_FUNC( void ) FT_Forget_Frame( FT_Stream stream )
247 {
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). */
252 /* */
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. */
256 /* */
257 FT_Assert( stream );
258
259 if ( stream->read )
260 {
261 FT_Memory memory = stream->memory;
262
263
264 FREE( stream->base );
265 }
266 stream->cursor = 0;
267 stream->limit = 0;
268 }
269
270
271 BASE_FUNC( FT_Char ) FT_Get_Char( FT_Stream stream )
272 {
273 FT_Char result;
274
275
276 FT_Assert( stream && stream->cursor );
277
278 result = 0;
279 if ( stream->cursor < stream->limit )
280 result = *stream->cursor++;
281
282 return result;
283 }
284
285
286 BASE_FUNC( FT_Short ) FT_Get_Short( FT_Stream stream )
287 {
288 FT_Byte* p;
289 FT_Short result;
290
291
292 FT_Assert( stream && stream->cursor );
293
294 result = 0;
295 p = stream->cursor;
296 if ( p + 1 < stream->limit )
297 result = NEXT_Short( p );
298 stream->cursor = p;
299
300 return result;
301 }
302
303
304 BASE_FUNC( FT_Short ) FT_Get_ShortLE( FT_Stream stream )
305 {
306 FT_Byte* p;
307 FT_Short result;
308
309
310 FT_Assert( stream && stream->cursor );
311
312 result = 0;
313 p = stream->cursor;
314 if ( p + 1 < stream->limit )
315 result = NEXT_ShortLE( p );
316 stream->cursor = p;
317
318 return result;
319 }
320
321
322 BASE_FUNC( FT_Long ) FT_Get_Offset( FT_Stream stream )
323 {
324 FT_Byte* p;
325 FT_Long result;
326
327
328 FT_Assert( stream && stream->cursor );
329
330 result = 0;
331 p = stream->cursor;
332 if ( p + 2 < stream->limit )
333 result = NEXT_Offset( p );
334 stream->cursor = p;
335 return result;
336 }
337
338
339 BASE_FUNC( FT_Long ) FT_Get_Long( FT_Stream stream )
340 {
341 FT_Byte* p;
342 FT_Long result;
343
344
345 FT_Assert( stream && stream->cursor );
346
347 result = 0;
348 p = stream->cursor;
349 if ( p + 3 < stream->limit )
350 result = NEXT_Long( p );
351 stream->cursor = p;
352 return result;
353 }
354
355
356 BASE_FUNC( FT_Long ) FT_Get_LongLE( FT_Stream stream )
357 {
358 FT_Byte* p;
359 FT_Long result;
360
361
362 FT_Assert( stream && stream->cursor );
363
364 result = 0;
365 p = stream->cursor;
366 if ( p + 3 < stream->limit )
367 result = NEXT_LongLE( p );
368 stream->cursor = p;
369 return result;
370 }
371
372
373 BASE_FUNC( FT_Char ) FT_Read_Char( FT_Stream stream,
374 FT_Error* error )
375 {
376 FT_Byte result = 0;
377
378
379 FT_Assert( stream );
380
381 *error = FT_Err_Ok;
382
383 if ( stream->read )
384 {
385 if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
386 goto Fail;
387 }
388 else
389 {
390 if ( stream->pos < stream->size )
391 result = stream->base[stream->pos];
392 else
393 goto Fail;
394 }
395 stream->pos++;
396
397 return result;
398
399 Fail:
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 ));
404
405 return 0;
406 }
407
408
409 BASE_FUNC( FT_Short ) FT_Read_Short( FT_Stream stream,
410 FT_Error* error )
411 {
412 FT_Byte reads[2];
413 FT_Byte* p = 0;
414 FT_Short result = 0;
415
416
417 FT_Assert( stream );
418
419 *error = FT_Err_Ok;
420
421 if ( stream->pos + 1 < stream->size )
422 {
423 if ( stream->read )
424 {
425 if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
426 goto Fail;
427
428 p = reads;
429 }
430 else
431 {
432 p = stream->base + stream->pos;
433 }
434
435 if ( p )
436 result = NEXT_Short( p );
437 }
438 else
439 goto Fail;
440
441 stream->pos += 2;
442
443 return result;
444
445 Fail:
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 ));
450
451 return 0;
452 }
453
454
455 BASE_FUNC( FT_Short ) FT_Read_ShortLE( FT_Stream stream,
456 FT_Error* error )
457 {
458 FT_Byte reads[2];
459 FT_Byte* p = 0;
460 FT_Short result = 0;
461
462
463 FT_Assert( stream );
464
465 *error = FT_Err_Ok;
466
467 if ( stream->pos + 1 < stream->size )
468 {
469 if ( stream->read )
470 {
471 if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
472 goto Fail;
473
474 p = reads;
475 }
476 else
477 {
478 p = stream->base + stream->pos;
479 }
480
481 if ( p )
482 result = NEXT_ShortLE( p );
483 }
484 else
485 goto Fail;
486
487 stream->pos += 2;
488
489 return result;
490
491 Fail:
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 ));
496
497 return 0;
498 }
499
500
501 BASE_FUNC( FT_Long ) FT_Read_Offset( FT_Stream stream,
502 FT_Error* error )
503 {
504 FT_Byte reads[3];
505 FT_Byte* p = 0;
506 FT_Long result = 0;
507
508
509 FT_Assert( stream );
510
511 *error = FT_Err_Ok;
512
513 if ( stream->pos + 2 < stream->size )
514 {
515 if ( stream->read )
516 {
517 if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
518 goto Fail;
519
520 p = reads;
521 }
522 else
523 {
524 p = stream->base + stream->pos;
525 }
526
527 if ( p )
528 result = NEXT_Offset( p );
529 }
530 else
531 goto Fail;
532
533 stream->pos += 3;
534
535 return result;
536
537 Fail:
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 ));
542
543 return 0;
544 }
545
546
547 BASE_FUNC( FT_Long ) FT_Read_Long( FT_Stream stream,
548 FT_Error* error )
549 {
550 FT_Byte reads[4];
551 FT_Byte* p = 0;
552 FT_Long result = 0;
553
554
555 FT_Assert( stream );
556
557 *error = FT_Err_Ok;
558
559 if ( stream->pos + 3 < stream->size )
560 {
561 if ( stream->read )
562 {
563 if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
564 goto Fail;
565
566 p = reads;
567 }
568 else
569 {
570 p = stream->base + stream->pos;
571 }
572
573 if ( p )
574 result = NEXT_Long( p );
575 }
576 else
577 goto Fail;
578
579 stream->pos += 4;
580
581 return result;
582
583 Fail:
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;
588
589 return 0;
590 }
591
592
593 BASE_FUNC( FT_Long ) FT_Read_LongLE( FT_Stream stream,
594 FT_Error* error )
595 {
596 FT_Byte reads[4];
597 FT_Byte* p = 0;
598 FT_Long result = 0;
599
600
601 FT_Assert( stream );
602
603 *error = FT_Err_Ok;
604
605 if ( stream->pos + 3 < stream->size )
606 {
607 if ( stream->read )
608 {
609 if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
610 goto Fail;
611
612 p = reads;
613 }
614 else
615 {
616 p = stream->base + stream->pos;
617 }
618
619 if ( p )
620 result = NEXT_LongLE( p );
621 }
622 else
623 goto Fail;
624
625 stream->pos += 4;
626
627 return result;
628
629 Fail:
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;
634
635 return 0;
636 }
637
638
639 BASE_FUNC( FT_Error ) FT_Read_Fields( FT_Stream stream,
640 const FT_Frame_Field* fields,
641 void* structure )
642 {
643 FT_Error error;
644 FT_Bool frame_accessed = 0;
645
646
647 if ( !fields || !stream )
648 return FT_Err_Invalid_Argument;
649
650 error = FT_Err_Ok;
651 do
652 {
653 FT_ULong value;
654 FT_Int sign_shift;
655 FT_Byte* p;
656
657
658 switch ( fields->value )
659 {
660 case ft_frame_start: /* access a new frame */
661 error = FT_Access_Frame( stream, fields->offset );
662 if ( error )
663 goto Exit;
664
665 frame_accessed = 1;
666 fields++;
667 continue; /* loop! */
668
669 case ft_frame_bytes: /* read a byte sequence */
670 case ft_frame_skip: /* skip some bytes */
671 {
672 FT_Int len = fields->size;
673
674
675 if ( stream->cursor + len > stream->limit )
676 {
677 error = FT_Err_Invalid_Stream_Operation;
678 goto Exit;
679 }
680
681 if ( fields->value == ft_frame_bytes )
682 {
683 p = (FT_Byte*)structure + fields->offset;
684 MEM_Copy( p, stream->cursor, len );
685 }
686 stream->cursor += len;
687 fields++;
688 continue;
689 }
690
691 case ft_frame_byte:
692 case ft_frame_schar: /* read a single byte */
693 value = GET_Byte();
694 sign_shift = 24;
695 break;
696
697 case ft_frame_short_be:
698 case ft_frame_ushort_be: /* read a 2-byte big-endian short */
699 value = GET_UShort();
700 sign_shift = 16;
701 break;
702
703 case ft_frame_short_le:
704 case ft_frame_ushort_le: /* read a 2-byte little-endian short */
705 {
706 FT_Byte* p;
707
708
709 value = 0;
710 p = stream->cursor;
711
712 if ( p + 1 < stream->limit )
713 {
714 value = ( FT_UShort)p[0] | ((FT_UShort)p[1] << 8 );
715 stream->cursor += 2;
716 }
717 sign_shift = 16;
718 break;
719 }
720
721 case ft_frame_long_be:
722 case ft_frame_ulong_be: /* read a 4-byte big-endian long */
723 value = GET_ULong();
724 sign_shift = 0;
725 break;
726
727 case ft_frame_long_le:
728 case ft_frame_ulong_le: /* read a 4-byte little-endian long */
729 {
730 FT_Byte* p;
731
732
733 value = 0;
734 p = stream->cursor;
735
736 if ( p + 3 < stream->limit )
737 {
738 value = (FT_ULong)p[0] |
739 ( (FT_ULong)p[1] << 8 ) |
740 ( (FT_ULong)p[2] << 16 ) |
741 ( (FT_ULong)p[3] << 24 );
742 stream->cursor += 4;
743 }
744 sign_shift = 0;
745 break;
746 }
747
748 case ft_frame_off3_be:
749 case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
750 value = GET_UOffset();
751 sign_shift = 8;
752 break;
753
754 case ft_frame_off3_le:
755 case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
756 {
757 FT_Byte* p;
758
759
760 value = 0;
761 p = stream->cursor;
762
763 if ( p + 2 < stream->limit )
764 {
765 value = (FT_ULong)p[0] |
766 ( (FT_ULong)p[1] << 8 ) |
767 ( (FT_ULong)p[2] << 16 );
768 stream->cursor += 3;
769 }
770 sign_shift = 8;
771 break;
772 }
773
774 default:
775 /* otherwise, exit the loop */
776 goto Exit;
777 }
778
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 );
782
783 /* finally, store the value in the object */
784
785 p = (FT_Byte*)structure + fields->offset;
786 switch ( fields->size )
787 {
788 case 1:
789 *(FT_Byte*)p = (FT_Byte)value;
790 break;
791
792 case 2:
793 *(FT_UShort*)p = (FT_UShort)value;
794 break;
795
796 case 4:
797 *(FT_UInt32*)p = (FT_UInt32)value;
798 break;
799
800 default: /* for 64-bit systems */
801 *(FT_ULong*)p = (FT_ULong)value;
802 }
803
804 /* go to next field */
805 fields++;
806 }
807 while ( 1 );
808
809 Exit:
810 /* close the frame if it was opened by this read */
811 if ( frame_accessed )
812 FT_Forget_Frame( stream );
813
814 return error;
815 }
816
817
818/* END */