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