source: trunk/poppler/freetype2/src/base/ftstream.c @ 262

Last change on this file since 262 was 262, checked in by Eugene Romanenko, 12 years ago

PDF plugin: freetype library updated to version 2.3.8

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