:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / subsys / win32k / freetype / src / base / ftstream.c
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 */