XFA: merge patch from CL 817753002
[pdfium.git] / core / src / fxge / fx_freetype / fxft2.5.01 / src / base / ftstream.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftstream.c                                                             */
4 /*                                                                         */
5 /*    I/O stream support (body).                                           */
6 /*                                                                         */
7 /*  Copyright 2000-2002, 2004-2006, 2008-2011, 2013 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 "../../include/ft2build.h"
20 #include "../../include/freetype/internal/ftstream.h"
21 #include "../../include/freetype/internal/ftdebug.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_Stream_OpenMemory( FT_Stream       stream,
36                         const FT_Byte*  base,
37                         FT_ULong        size )
38   {
39     stream->base   = (FT_Byte*) 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   FT_BASE_DEF( void )
49   FT_Stream_Close( FT_Stream  stream )
50   {
51     if ( stream && stream->close )
52       stream->close( stream );
53   }
54
55
56   FT_BASE_DEF( FT_Error )
57   FT_Stream_Seek( FT_Stream  stream,
58                   FT_ULong   pos )
59   {
60     FT_Error  error = FT_Err_Ok;
61
62
63     if ( stream->read )
64     {
65       if ( stream->read( stream, pos, 0, 0 ) )
66       {
67         FT_ERROR(( "FT_Stream_Seek:"
68                    " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
69                    pos, stream->size ));
70
71         error = FT_THROW( Invalid_Stream_Operation );
72       }
73     }
74     /* note that seeking to the first position after the file is valid */
75     else if ( pos > stream->size )
76     {
77       FT_ERROR(( "FT_Stream_Seek:"
78                  " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
79                  pos, stream->size ));
80
81       error = FT_THROW( Invalid_Stream_Operation );
82     }
83
84     if ( !error )
85       stream->pos = pos;
86
87     return error;
88   }
89
90
91   FT_BASE_DEF( FT_Error )
92   FT_Stream_Skip( FT_Stream  stream,
93                   FT_Long    distance )
94   {
95     if ( distance < 0 )
96       return FT_THROW( Invalid_Stream_Operation );
97
98     return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
99   }
100
101
102   FT_BASE_DEF( FT_Long )
103   FT_Stream_Pos( FT_Stream  stream )
104   {
105     return stream->pos;
106   }
107
108
109   FT_BASE_DEF( FT_Error )
110   FT_Stream_Read( FT_Stream  stream,
111                   FT_Byte*   buffer,
112                   FT_ULong   count )
113   {
114     return FT_Stream_ReadAt( stream, stream->pos, buffer, count );
115   }
116
117
118   FT_BASE_DEF( FT_Error )
119   FT_Stream_ReadAt( FT_Stream  stream,
120                     FT_ULong   pos,
121                     FT_Byte*   buffer,
122                     FT_ULong   count )
123   {
124     FT_Error  error = FT_Err_Ok;
125     FT_ULong  read_bytes;
126
127
128     if ( pos >= stream->size )
129     {
130       FT_ERROR(( "FT_Stream_ReadAt:"
131                  " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
132                  pos, stream->size ));
133
134       return FT_THROW( Invalid_Stream_Operation );
135     }
136
137     if ( stream->read )
138       read_bytes = stream->read( stream, pos, buffer, count );
139     else
140     {
141       read_bytes = stream->size - pos;
142       if ( read_bytes > count )
143         read_bytes = count;
144
145       FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
146     }
147
148     stream->pos = pos + read_bytes;
149
150     if ( read_bytes < count )
151     {
152       FT_ERROR(( "FT_Stream_ReadAt:"
153                  " invalid read; expected %lu bytes, got %lu\n",
154                  count, read_bytes ));
155
156       error = FT_THROW( Invalid_Stream_Operation );
157     }
158
159     return error;
160   }
161
162
163   FT_BASE_DEF( FT_ULong )
164   FT_Stream_TryRead( FT_Stream  stream,
165                      FT_Byte*   buffer,
166                      FT_ULong   count )
167   {
168     FT_ULong  read_bytes = 0;
169
170
171     if ( stream->pos >= stream->size )
172       goto Exit;
173
174     if ( stream->read )
175       read_bytes = stream->read( stream, stream->pos, buffer, count );
176     else
177     {
178       read_bytes = stream->size - stream->pos;
179       if ( read_bytes > count )
180         read_bytes = count;
181
182       FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
183     }
184
185     stream->pos += read_bytes;
186
187   Exit:
188     return read_bytes;
189   }
190
191
192   FT_BASE_DEF( FT_Error )
193   FT_Stream_ExtractFrame( FT_Stream  stream,
194                           FT_ULong   count,
195                           FT_Byte**  pbytes )
196   {
197     FT_Error  error;
198
199
200     error = FT_Stream_EnterFrame( stream, count );
201     if ( !error )
202     {
203       *pbytes = (FT_Byte*)stream->cursor;
204
205       /* equivalent to FT_Stream_ExitFrame(), with no memory block release */
206       stream->cursor = 0;
207       stream->limit  = 0;
208     }
209
210     return error;
211   }
212
213
214   FT_BASE_DEF( void )
215   FT_Stream_ReleaseFrame( FT_Stream  stream,
216                           FT_Byte**  pbytes )
217   {
218     if ( stream && stream->read )
219     {
220       FT_Memory  memory = stream->memory;
221
222 #ifdef FT_DEBUG_MEMORY
223       ft_mem_free( memory, *pbytes );
224       *pbytes = NULL;
225 #else
226       FT_FREE( *pbytes );
227 #endif
228     }
229     *pbytes = 0;
230   }
231
232
233   FT_BASE_DEF( FT_Error )
234   FT_Stream_EnterFrame( FT_Stream  stream,
235                         FT_ULong   count )
236   {
237     FT_Error  error = FT_Err_Ok;
238     FT_ULong  read_bytes;
239
240
241     /* check for nested frame access */
242     FT_ASSERT( stream && stream->cursor == 0 );
243
244     if ( stream->read )
245     {
246       /* allocate the frame in memory */
247       FT_Memory  memory = stream->memory;
248
249
250       /* simple sanity check */
251       if ( count > stream->size )
252       {
253         FT_ERROR(( "FT_Stream_EnterFrame:"
254                    " frame size (%lu) larger than stream size (%lu)\n",
255                    count, stream->size ));
256
257         error = FT_THROW( Invalid_Stream_Operation );
258         goto Exit;
259       }
260
261 #ifdef FT_DEBUG_MEMORY
262       /* assume _ft_debug_file and _ft_debug_lineno are already set */
263       stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );
264       if ( error )
265         goto Exit;
266 #else
267       if ( FT_QALLOC( stream->base, count ) )
268         goto Exit;
269 #endif
270       /* read it */
271       read_bytes = stream->read( stream, stream->pos,
272                                  stream->base, count );
273       if ( read_bytes < count )
274       {
275         FT_ERROR(( "FT_Stream_EnterFrame:"
276                    " invalid read; expected %lu bytes, got %lu\n",
277                    count, read_bytes ));
278
279         FT_FREE( stream->base );
280         error = FT_THROW( Invalid_Stream_Operation );
281       }
282       stream->cursor = stream->base;
283       stream->limit  = stream->cursor + count;
284       stream->pos   += read_bytes;
285     }
286     else
287     {
288       /* check current and new position */
289       if ( stream->pos >= stream->size        ||
290            stream->size - stream->pos < count )
291       {
292         FT_ERROR(( "FT_Stream_EnterFrame:"
293                    " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
294                    stream->pos, count, stream->size ));
295
296         error = FT_THROW( Invalid_Stream_Operation );
297         goto Exit;
298       }
299
300       /* set cursor */
301       stream->cursor = stream->base + stream->pos;
302       stream->limit  = stream->cursor + count;
303       stream->pos   += count;
304     }
305
306   Exit:
307     return error;
308   }
309
310
311   FT_BASE_DEF( void )
312   FT_Stream_ExitFrame( FT_Stream  stream )
313   {
314     /* IMPORTANT: The assertion stream->cursor != 0 was removed, given    */
315     /*            that it is possible to access a frame of length 0 in    */
316     /*            some weird fonts (usually, when accessing an array of   */
317     /*            0 records, like in some strange kern tables).           */
318     /*                                                                    */
319     /*  In this case, the loader code handles the 0-length table          */
320     /*  gracefully; however, stream.cursor is really set to 0 by the      */
321     /*  FT_Stream_EnterFrame() call, and this is not an error.            */
322     /*                                                                    */
323     FT_ASSERT( stream );
324
325     if ( stream->read )
326     {
327       FT_Memory  memory = stream->memory;
328
329 #ifdef FT_DEBUG_MEMORY
330       ft_mem_free( memory, stream->base );
331       stream->base = NULL;
332 #else
333       FT_FREE( stream->base );
334 #endif
335     }
336     stream->cursor = 0;
337     stream->limit  = 0;
338   }
339
340
341   FT_BASE_DEF( FT_Char )
342   FT_Stream_GetChar( FT_Stream  stream )
343   {
344     FT_Char  result;
345
346
347     FT_ASSERT( stream && stream->cursor );
348
349     result = 0;
350     if ( stream->cursor < stream->limit )
351       result = *stream->cursor++;
352
353     return result;
354   }
355
356
357   FT_BASE_DEF( FT_UShort )
358   FT_Stream_GetUShort( FT_Stream  stream )
359   {
360     FT_Byte*  p;
361     FT_Short  result;
362
363
364     FT_ASSERT( stream && stream->cursor );
365
366     result         = 0;
367     p              = stream->cursor;
368     if ( p + 1 < stream->limit )
369       result       = FT_NEXT_USHORT( p );
370     stream->cursor = p;
371
372     return result;
373   }
374
375
376   FT_BASE_DEF( FT_UShort )
377   FT_Stream_GetUShortLE( FT_Stream  stream )
378   {
379     FT_Byte*  p;
380     FT_Short  result;
381
382
383     FT_ASSERT( stream && stream->cursor );
384
385     result         = 0;
386     p              = stream->cursor;
387     if ( p + 1 < stream->limit )
388       result       = FT_NEXT_USHORT_LE( p );
389     stream->cursor = p;
390
391     return result;
392   }
393
394
395   FT_BASE_DEF( FT_ULong )
396   FT_Stream_GetUOffset( FT_Stream  stream )
397   {
398     FT_Byte*  p;
399     FT_Long   result;
400
401
402     FT_ASSERT( stream && stream->cursor );
403
404     result         = 0;
405     p              = stream->cursor;
406     if ( p + 2 < stream->limit )
407       result       = FT_NEXT_UOFF3( p );
408     stream->cursor = p;
409     return result;
410   }
411
412
413   FT_BASE_DEF( FT_ULong )
414   FT_Stream_GetULong( FT_Stream  stream )
415   {
416     FT_Byte*  p;
417     FT_Long   result;
418
419
420     FT_ASSERT( stream && stream->cursor );
421
422     result         = 0;
423     p              = stream->cursor;
424     if ( p + 3 < stream->limit )
425       result       = FT_NEXT_ULONG( p );
426     stream->cursor = p;
427     return result;
428   }
429
430
431   FT_BASE_DEF( FT_ULong )
432   FT_Stream_GetULongLE( FT_Stream  stream )
433   {
434     FT_Byte*  p;
435     FT_Long   result;
436
437
438     FT_ASSERT( stream && stream->cursor );
439
440     result         = 0;
441     p              = stream->cursor;
442     if ( p + 3 < stream->limit )
443       result       = FT_NEXT_ULONG_LE( p );
444     stream->cursor = p;
445     return result;
446   }
447
448
449   FT_BASE_DEF( FT_Char )
450   FT_Stream_ReadChar( FT_Stream  stream,
451                       FT_Error*  error )
452   {
453     FT_Byte  result = 0;
454
455
456     FT_ASSERT( stream );
457
458     *error = FT_Err_Ok;
459
460     if ( stream->read )
461     {
462       if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
463         goto Fail;
464     }
465     else
466     {
467       if ( stream->pos < stream->size )
468         result = stream->base[stream->pos];
469       else
470         goto Fail;
471     }
472     stream->pos++;
473
474     return result;
475
476   Fail:
477     *error = FT_THROW( Invalid_Stream_Operation );
478     FT_ERROR(( "FT_Stream_ReadChar:"
479                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
480                stream->pos, stream->size ));
481
482     return 0;
483   }
484
485
486   FT_BASE_DEF( FT_UShort )
487   FT_Stream_ReadUShort( FT_Stream  stream,
488                        FT_Error*  error )
489   {
490     FT_Byte   reads[2];
491     FT_Byte*  p = 0;
492     FT_Short  result = 0;
493
494
495     FT_ASSERT( stream );
496
497     *error = FT_Err_Ok;
498
499     if ( stream->pos + 1 < stream->size )
500     {
501       if ( stream->read )
502       {
503         if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
504           goto Fail;
505
506         p = reads;
507       }
508       else
509       {
510         p = stream->base + stream->pos;
511       }
512
513       if ( p )
514         result = FT_NEXT_USHORT( p );
515     }
516     else
517       goto Fail;
518
519     stream->pos += 2;
520
521     return result;
522
523   Fail:
524     *error = FT_THROW( Invalid_Stream_Operation );
525     FT_ERROR(( "FT_Stream_ReadUShort:"
526                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
527                stream->pos, stream->size ));
528
529     return 0;
530   }
531
532
533   FT_BASE_DEF( FT_UShort )
534   FT_Stream_ReadUShortLE( FT_Stream  stream,
535                          FT_Error*  error )
536   {
537     FT_Byte   reads[2];
538     FT_Byte*  p = 0;
539     FT_Short  result = 0;
540
541
542     FT_ASSERT( stream );
543
544     *error = FT_Err_Ok;
545
546     if ( stream->pos + 1 < stream->size )
547     {
548       if ( stream->read )
549       {
550         if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
551           goto Fail;
552
553         p = reads;
554       }
555       else
556       {
557         p = stream->base + stream->pos;
558       }
559
560       if ( p )
561         result = FT_NEXT_USHORT_LE( p );
562     }
563     else
564       goto Fail;
565
566     stream->pos += 2;
567
568     return result;
569
570   Fail:
571     *error = FT_THROW( Invalid_Stream_Operation );
572     FT_ERROR(( "FT_Stream_ReadUShortLE:"
573                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
574                stream->pos, stream->size ));
575
576     return 0;
577   }
578
579
580   FT_BASE_DEF( FT_ULong )
581   FT_Stream_ReadUOffset( FT_Stream  stream,
582                         FT_Error*  error )
583   {
584     FT_Byte   reads[3];
585     FT_Byte*  p = 0;
586     FT_Long   result = 0;
587
588
589     FT_ASSERT( stream );
590
591     *error = FT_Err_Ok;
592
593     if ( stream->pos + 2 < stream->size )
594     {
595       if ( stream->read )
596       {
597         if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
598           goto Fail;
599
600         p = reads;
601       }
602       else
603       {
604         p = stream->base + stream->pos;
605       }
606
607       if ( p )
608         result = FT_NEXT_UOFF3( p );
609     }
610     else
611       goto Fail;
612
613     stream->pos += 3;
614
615     return result;
616
617   Fail:
618     *error = FT_THROW( Invalid_Stream_Operation );
619     FT_ERROR(( "FT_Stream_ReadUOffset:"
620                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
621                stream->pos, stream->size ));
622
623     return 0;
624   }
625
626
627   FT_BASE_DEF( FT_ULong )
628   FT_Stream_ReadULong( FT_Stream  stream,
629                       FT_Error*  error )
630   {
631     FT_Byte   reads[4];
632     FT_Byte*  p = 0;
633     FT_Long   result = 0;
634
635
636     FT_ASSERT( stream );
637
638     *error = FT_Err_Ok;
639
640     if ( stream->pos + 3 < stream->size )
641     {
642       if ( stream->read )
643       {
644         if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
645           goto Fail;
646
647         p = reads;
648       }
649       else
650       {
651         p = stream->base + stream->pos;
652       }
653
654       if ( p )
655         result = FT_NEXT_ULONG( p );
656     }
657     else
658       goto Fail;
659
660     stream->pos += 4;
661
662     return result;
663
664   Fail:
665     *error = FT_THROW( Invalid_Stream_Operation );
666     FT_ERROR(( "FT_Stream_ReadULong:"
667                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
668                stream->pos, stream->size ));
669
670     return 0;
671   }
672
673
674   FT_BASE_DEF( FT_ULong )
675   FT_Stream_ReadULongLE( FT_Stream  stream,
676                         FT_Error*  error )
677   {
678     FT_Byte   reads[4];
679     FT_Byte*  p = 0;
680     FT_Long   result = 0;
681
682
683     FT_ASSERT( stream );
684
685     *error = FT_Err_Ok;
686
687     if ( stream->pos + 3 < stream->size )
688     {
689       if ( stream->read )
690       {
691         if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
692           goto Fail;
693
694         p = reads;
695       }
696       else
697       {
698         p = stream->base + stream->pos;
699       }
700
701       if ( p )
702         result = FT_NEXT_ULONG_LE( p );
703     }
704     else
705       goto Fail;
706
707     stream->pos += 4;
708
709     return result;
710
711   Fail:
712     *error = FT_THROW( Invalid_Stream_Operation );
713     FT_ERROR(( "FT_Stream_ReadULongLE:"
714                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
715                stream->pos, stream->size ));
716
717     return 0;
718   }
719
720
721   FT_BASE_DEF( FT_Error )
722   FT_Stream_ReadFields( FT_Stream              stream,
723                         const FT_Frame_Field*  fields,
724                         void*                  structure )
725   {
726     FT_Error  error;
727     FT_Bool   frame_accessed = 0;
728     FT_Byte*  cursor;
729
730
731     if ( !fields || !stream )
732       return FT_THROW( Invalid_Argument );
733
734     cursor = stream->cursor;
735
736     error = FT_Err_Ok;
737     do
738     {
739       FT_ULong  value;
740       FT_Int    sign_shift;
741       FT_Byte*  p;
742
743
744       switch ( fields->value )
745       {
746       case ft_frame_start:  /* access a new frame */
747         error = FT_Stream_EnterFrame( stream, fields->offset );
748         if ( error )
749           goto Exit;
750
751         frame_accessed = 1;
752         cursor         = stream->cursor;
753         fields++;
754         continue;  /* loop! */
755
756       case ft_frame_bytes:  /* read a byte sequence */
757       case ft_frame_skip:   /* skip some bytes      */
758         {
759           FT_UInt  len = fields->size;
760
761
762           if ( cursor + len > stream->limit )
763           {
764             error = FT_THROW( Invalid_Stream_Operation );
765             goto Exit;
766           }
767
768           if ( fields->value == ft_frame_bytes )
769           {
770             p = (FT_Byte*)structure + fields->offset;
771             FT_MEM_COPY( p, cursor, len );
772           }
773           cursor += len;
774           fields++;
775           continue;
776         }
777
778       case ft_frame_byte:
779       case ft_frame_schar:  /* read a single byte */
780         value = FT_NEXT_BYTE( cursor );
781         sign_shift = 24;
782         break;
783
784       case ft_frame_short_be:
785       case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
786         value = FT_NEXT_USHORT( cursor) ;
787         sign_shift = 16;
788         break;
789
790       case ft_frame_short_le:
791       case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
792         value = FT_NEXT_USHORT_LE( cursor );
793         sign_shift = 16;
794         break;
795
796       case ft_frame_long_be:
797       case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
798         value = FT_NEXT_ULONG( cursor );
799         sign_shift = 0;
800         break;
801
802       case ft_frame_long_le:
803       case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
804         value = FT_NEXT_ULONG_LE( cursor );
805         sign_shift = 0;
806         break;
807
808       case ft_frame_off3_be:
809       case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
810         value = FT_NEXT_UOFF3( cursor );
811         sign_shift = 8;
812         break;
813
814       case ft_frame_off3_le:
815       case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
816         value = FT_NEXT_UOFF3_LE( cursor );
817         sign_shift = 8;
818         break;
819
820       default:
821         /* otherwise, exit the loop */
822         stream->cursor = cursor;
823         goto Exit;
824       }
825
826       /* now, compute the signed value is necessary */
827       if ( fields->value & FT_FRAME_OP_SIGNED )
828         value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
829
830       /* finally, store the value in the object */
831
832       p = (FT_Byte*)structure + fields->offset;
833       switch ( fields->size )
834       {
835       case ( 8 / FT_CHAR_BIT ):
836         *(FT_Byte*)p = (FT_Byte)value;
837         break;
838
839       case ( 16 / FT_CHAR_BIT ):
840         *(FT_UShort*)p = (FT_UShort)value;
841         break;
842
843       case ( 32 / FT_CHAR_BIT ):
844         *(FT_UInt32*)p = (FT_UInt32)value;
845         break;
846
847       default:  /* for 64-bit systems */
848         *(FT_ULong*)p = (FT_ULong)value;
849       }
850
851       /* go to next field */
852       fields++;
853     }
854     while ( 1 );
855
856   Exit:
857     /* close the frame if it was opened by this read */
858     if ( frame_accessed )
859       FT_Stream_ExitFrame( stream );
860
861     return error;
862   }
863
864
865 /* END */