~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/base/ftstream.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  ftstream.c                                                             */
 
4
/*                                                                         */
 
5
/*    I/O stream support (body).                                           */
 
6
/*                                                                         */
 
7
/*  Copyright 2000-2001, 2002, 2004 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
    {
 
53
      stream->close( stream );
 
54
      stream->close = NULL;
 
55
    }
 
56
  }
 
57
 
 
58
 
 
59
  FT_BASE_DEF( FT_Error )
 
60
  FT_Stream_Seek( FT_Stream  stream,
 
61
                  FT_ULong   pos )
 
62
  {
 
63
    FT_Error  error = FT_Err_Ok;
 
64
 
 
65
 
 
66
    stream->pos = pos;
 
67
 
 
68
    if ( stream->read )
 
69
    {
 
70
      if ( stream->read( stream, pos, 0, 0 ) )
 
71
      {
 
72
        FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
73
                   pos, stream->size ));
 
74
 
 
75
        error = FT_Err_Invalid_Stream_Operation;
 
76
      }
 
77
    }
 
78
    /* note that seeking to the first position after the file is valid */
 
79
    else if ( pos > stream->size )
 
80
    {
 
81
      FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
82
                 pos, stream->size ));
 
83
 
 
84
      error = FT_Err_Invalid_Stream_Operation;
 
85
    }
 
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
    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_Error )
 
160
  FT_Stream_ExtractFrame( FT_Stream  stream,
 
161
                          FT_ULong   count,
 
162
                          FT_Byte**  pbytes )
 
163
  {
 
164
    FT_Error  error;
 
165
 
 
166
 
 
167
    error = FT_Stream_EnterFrame( stream, count );
 
168
    if ( !error )
 
169
    {
 
170
      *pbytes = (FT_Byte*)stream->cursor;
 
171
 
 
172
      /* equivalent to FT_Stream_ExitFrame(), with no memory block release */
 
173
      stream->cursor = 0;
 
174
      stream->limit  = 0;
 
175
    }
 
176
 
 
177
    return error;
 
178
  }
 
179
 
 
180
 
 
181
  FT_BASE_DEF( void )
 
182
  FT_Stream_ReleaseFrame( FT_Stream  stream,
 
183
                          FT_Byte**  pbytes )
 
184
  {
 
185
    if ( stream->read )
 
186
    {
 
187
      FT_Memory  memory = stream->memory;
 
188
 
 
189
 
 
190
      FT_FREE( *pbytes );
 
191
    }
 
192
    *pbytes = 0;
 
193
  }
 
194
 
 
195
 
 
196
  FT_BASE_DEF( FT_Error )
 
197
  FT_Stream_EnterFrame( FT_Stream  stream,
 
198
                        FT_ULong   count )
 
199
  {
 
200
    FT_Error  error = FT_Err_Ok;
 
201
    FT_ULong  read_bytes;
 
202
 
 
203
 
 
204
    /* check for nested frame access */
 
205
    FT_ASSERT( stream && stream->cursor == 0 );
 
206
 
 
207
    if ( stream->read )
 
208
    {
 
209
      /* allocate the frame in memory */
 
210
      FT_Memory  memory = stream->memory;
 
211
 
 
212
 
 
213
      if ( FT_QALLOC( stream->base, count ) )
 
214
        goto Exit;
 
215
 
 
216
      /* read it */
 
217
      read_bytes = stream->read( stream, stream->pos,
 
218
                                 stream->base, count );
 
219
      if ( read_bytes < count )
 
220
      {
 
221
        FT_ERROR(( "FT_Stream_EnterFrame:" ));
 
222
        FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
 
223
                   count, read_bytes ));
 
224
 
 
225
        FT_FREE( stream->base );
 
226
        error = FT_Err_Invalid_Stream_Operation;
 
227
      }
 
228
      stream->cursor = stream->base;
 
229
      stream->limit  = stream->cursor + count;
 
230
      stream->pos   += read_bytes;
 
231
    }
 
232
    else
 
233
    {
 
234
      /* check current and new position */
 
235
      if ( stream->pos >= stream->size        ||
 
236
           stream->pos + count > stream->size )
 
237
      {
 
238
        FT_ERROR(( "FT_Stream_EnterFrame:" ));
 
239
        FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
 
240
                   stream->pos, count, stream->size ));
 
241
 
 
242
        error = FT_Err_Invalid_Stream_Operation;
 
243
        goto Exit;
 
244
      }
 
245
 
 
246
      /* set cursor */
 
247
      stream->cursor = stream->base + stream->pos;
 
248
      stream->limit  = stream->cursor + count;
 
249
      stream->pos   += count;
 
250
    }
 
251
 
 
252
  Exit:
 
253
    return error;
 
254
  }
 
255
 
 
256
 
 
257
  FT_BASE_DEF( void )
 
258
  FT_Stream_ExitFrame( FT_Stream  stream )
 
259
  {
 
260
    /* IMPORTANT: The assertion stream->cursor != 0 was removed, given    */
 
261
    /*            that it is possible to access a frame of length 0 in    */
 
262
    /*            some weird fonts (usually, when accessing an array of   */
 
263
    /*            0 records, like in some strange kern tables).           */
 
264
    /*                                                                    */
 
265
    /*  In this case, the loader code handles the 0-length table          */
 
266
    /*  gracefully; however, stream.cursor is really set to 0 by the      */
 
267
    /*  FT_Stream_EnterFrame() call, and this is not an error.            */
 
268
    /*                                                                    */
 
269
    FT_ASSERT( stream );
 
270
 
 
271
    if ( stream->read )
 
272
    {
 
273
      FT_Memory  memory = stream->memory;
 
274
 
 
275
 
 
276
      FT_FREE( stream->base );
 
277
    }
 
278
    stream->cursor = 0;
 
279
    stream->limit  = 0;
 
280
  }
 
281
 
 
282
 
 
283
  FT_BASE_DEF( FT_Char )
 
284
  FT_Stream_GetChar( FT_Stream  stream )
 
285
  {
 
286
    FT_Char  result;
 
287
 
 
288
 
 
289
    FT_ASSERT( stream && stream->cursor );
 
290
 
 
291
    result = 0;
 
292
    if ( stream->cursor < stream->limit )
 
293
      result = *stream->cursor++;
 
294
 
 
295
    return result;
 
296
  }
 
297
 
 
298
 
 
299
  FT_BASE_DEF( FT_Short )
 
300
  FT_Stream_GetShort( FT_Stream  stream )
 
301
  {
 
302
    FT_Byte*  p;
 
303
    FT_Short  result;
 
304
 
 
305
 
 
306
    FT_ASSERT( stream && stream->cursor );
 
307
 
 
308
    result         = 0;
 
309
    p              = stream->cursor;
 
310
    if ( p + 1 < stream->limit )
 
311
      result       = FT_NEXT_SHORT( p );
 
312
    stream->cursor = p;
 
313
 
 
314
    return result;
 
315
  }
 
316
 
 
317
 
 
318
  FT_BASE_DEF( FT_Short )
 
319
  FT_Stream_GetShortLE( FT_Stream  stream )
 
320
  {
 
321
    FT_Byte*  p;
 
322
    FT_Short  result;
 
323
 
 
324
 
 
325
    FT_ASSERT( stream && stream->cursor );
 
326
 
 
327
    result         = 0;
 
328
    p              = stream->cursor;
 
329
    if ( p + 1 < stream->limit )
 
330
      result       = FT_NEXT_SHORT_LE( p );
 
331
    stream->cursor = p;
 
332
 
 
333
    return result;
 
334
  }
 
335
 
 
336
 
 
337
  FT_BASE_DEF( FT_Long )
 
338
  FT_Stream_GetOffset( FT_Stream  stream )
 
339
  {
 
340
    FT_Byte*  p;
 
341
    FT_Long   result;
 
342
 
 
343
 
 
344
    FT_ASSERT( stream && stream->cursor );
 
345
 
 
346
    result         = 0;
 
347
    p              = stream->cursor;
 
348
    if ( p + 2 < stream->limit )
 
349
      result       = FT_NEXT_OFF3( p );
 
350
    stream->cursor = p;
 
351
    return result;
 
352
  }
 
353
 
 
354
 
 
355
  FT_BASE_DEF( FT_Long )
 
356
  FT_Stream_GetLong( 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       = FT_NEXT_LONG( p );
 
368
    stream->cursor = p;
 
369
    return result;
 
370
  }
 
371
 
 
372
 
 
373
  FT_BASE_DEF( FT_Long )
 
374
  FT_Stream_GetLongLE( FT_Stream  stream )
 
375
  {
 
376
    FT_Byte*  p;
 
377
    FT_Long   result;
 
378
 
 
379
 
 
380
    FT_ASSERT( stream && stream->cursor );
 
381
 
 
382
    result         = 0;
 
383
    p              = stream->cursor;
 
384
    if ( p + 3 < stream->limit )
 
385
      result       = FT_NEXT_LONG_LE( p );
 
386
    stream->cursor = p;
 
387
    return result;
 
388
  }
 
389
 
 
390
 
 
391
  FT_BASE_DEF( FT_Char )
 
392
  FT_Stream_ReadChar( FT_Stream  stream,
 
393
                      FT_Error*  error )
 
394
  {
 
395
    FT_Byte  result = 0;
 
396
 
 
397
 
 
398
    FT_ASSERT( stream );
 
399
 
 
400
    *error = FT_Err_Ok;
 
401
 
 
402
    if ( stream->read )
 
403
    {
 
404
      if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
 
405
        goto Fail;
 
406
    }
 
407
    else
 
408
    {
 
409
      if ( stream->pos < stream->size )
 
410
        result = stream->base[stream->pos];
 
411
      else
 
412
        goto Fail;
 
413
    }
 
414
    stream->pos++;
 
415
 
 
416
    return result;
 
417
 
 
418
  Fail:
 
419
    *error = FT_Err_Invalid_Stream_Operation;
 
420
    FT_ERROR(( "FT_Stream_ReadChar: 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_Stream_ReadShort( 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 = FT_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_Stream_ReadShort:" ));
 
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_Stream_ReadShortLE( 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 = FT_NEXT_SHORT_LE( 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_Stream_ReadShortLE:" ));
 
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_Stream_ReadOffset( 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 = FT_NEXT_OFF3( 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_Stream_ReadOffset:" ));
 
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_Stream_ReadLong( 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 = FT_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_Stream_ReadLong: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
607
               stream->pos, stream->size ));
 
608
    *error = FT_Err_Invalid_Stream_Operation;
 
609
 
 
610
    return 0;
 
611
  }
 
612
 
 
613
 
 
614
  FT_BASE_DEF( FT_Long )
 
615
  FT_Stream_ReadLongLE( FT_Stream  stream,
 
616
                        FT_Error*  error )
 
617
  {
 
618
    FT_Byte   reads[4];
 
619
    FT_Byte*  p = 0;
 
620
    FT_Long   result = 0;
 
621
 
 
622
 
 
623
    FT_ASSERT( stream );
 
624
 
 
625
    *error = FT_Err_Ok;
 
626
 
 
627
    if ( stream->pos + 3 < stream->size )
 
628
    {
 
629
      if ( stream->read )
 
630
      {
 
631
        if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
 
632
          goto Fail;
 
633
 
 
634
        p = reads;
 
635
      }
 
636
      else
 
637
      {
 
638
        p = stream->base + stream->pos;
 
639
      }
 
640
 
 
641
      if ( p )
 
642
        result = FT_NEXT_LONG_LE( p );
 
643
    }
 
644
    else
 
645
      goto Fail;
 
646
 
 
647
    stream->pos += 4;
 
648
 
 
649
    return result;
 
650
 
 
651
  Fail:
 
652
    FT_ERROR(( "FT_Stream_ReadLongLE:" ));
 
653
    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
654
               stream->pos, stream->size ));
 
655
    *error = FT_Err_Invalid_Stream_Operation;
 
656
 
 
657
    return 0;
 
658
  }
 
659
 
 
660
 
 
661
  FT_BASE_DEF( FT_Error )
 
662
  FT_Stream_ReadFields( FT_Stream              stream,
 
663
                        const FT_Frame_Field*  fields,
 
664
                        void*                  structure )
 
665
  {
 
666
    FT_Error  error;
 
667
    FT_Bool   frame_accessed = 0;
 
668
    FT_Byte*  cursor = stream->cursor;
 
669
 
 
670
 
 
671
    if ( !fields || !stream )
 
672
      return FT_Err_Invalid_Argument;
 
673
 
 
674
    error = FT_Err_Ok;
 
675
    do
 
676
    {
 
677
      FT_ULong  value;
 
678
      FT_Int    sign_shift;
 
679
      FT_Byte*  p;
 
680
 
 
681
 
 
682
      switch ( fields->value )
 
683
      {
 
684
      case ft_frame_start:  /* access a new frame */
 
685
        error = FT_Stream_EnterFrame( stream, fields->offset );
 
686
        if ( error )
 
687
          goto Exit;
 
688
 
 
689
        frame_accessed = 1;
 
690
        cursor         = stream->cursor;
 
691
        fields++;
 
692
        continue;  /* loop! */
 
693
 
 
694
      case ft_frame_bytes:  /* read a byte sequence */
 
695
      case ft_frame_skip:   /* skip some bytes      */
 
696
        {
 
697
          FT_UInt  len = fields->size;
 
698
 
 
699
 
 
700
          if ( cursor + len > stream->limit )
 
701
          {
 
702
            error = FT_Err_Invalid_Stream_Operation;
 
703
            goto Exit;
 
704
          }
 
705
 
 
706
          if ( fields->value == ft_frame_bytes )
 
707
          {
 
708
            p = (FT_Byte*)structure + fields->offset;
 
709
            FT_MEM_COPY( p, cursor, len );
 
710
          }
 
711
          cursor += len;
 
712
          fields++;
 
713
          continue;
 
714
        }
 
715
 
 
716
      case ft_frame_byte:
 
717
      case ft_frame_schar:  /* read a single byte */
 
718
        value = FT_NEXT_BYTE(cursor);
 
719
        sign_shift = 24;
 
720
        break;
 
721
 
 
722
      case ft_frame_short_be:
 
723
      case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
 
724
        value = FT_NEXT_USHORT(cursor);
 
725
        sign_shift = 16;
 
726
        break;
 
727
 
 
728
      case ft_frame_short_le:
 
729
      case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
 
730
        value = FT_NEXT_USHORT_LE(cursor);
 
731
        sign_shift = 16;
 
732
        break;
 
733
 
 
734
      case ft_frame_long_be:
 
735
      case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
 
736
        value = FT_NEXT_ULONG(cursor);
 
737
        sign_shift = 0;
 
738
        break;
 
739
 
 
740
      case ft_frame_long_le:
 
741
      case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
 
742
        value = FT_NEXT_ULONG_LE(cursor);
 
743
        sign_shift = 0;
 
744
        break;
 
745
 
 
746
      case ft_frame_off3_be:
 
747
      case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
 
748
        value = FT_NEXT_UOFF3(cursor);
 
749
        sign_shift = 8;
 
750
        break;
 
751
 
 
752
      case ft_frame_off3_le:
 
753
      case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
 
754
        value = FT_NEXT_UOFF3_LE(cursor);
 
755
        sign_shift = 8;
 
756
        break;
 
757
 
 
758
      default:
 
759
        /* otherwise, exit the loop */
 
760
        stream->cursor = cursor;
 
761
        goto Exit;
 
762
      }
 
763
 
 
764
      /* now, compute the signed value is necessary */
 
765
      if ( fields->value & FT_FRAME_OP_SIGNED )
 
766
        value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
 
767
 
 
768
      /* finally, store the value in the object */
 
769
 
 
770
      p = (FT_Byte*)structure + fields->offset;
 
771
      switch ( fields->size )
 
772
      {
 
773
      case (8 / FT_CHAR_BIT):
 
774
        *(FT_Byte*)p = (FT_Byte)value;
 
775
        break;
 
776
 
 
777
      case (16 / FT_CHAR_BIT):
 
778
        *(FT_UShort*)p = (FT_UShort)value;
 
779
        break;
 
780
 
 
781
      case (32 / FT_CHAR_BIT):
 
782
        *(FT_UInt32*)p = (FT_UInt32)value;
 
783
        break;
 
784
 
 
785
      default:  /* for 64-bit systems */
 
786
        *(FT_ULong*)p = (FT_ULong)value;
 
787
      }
 
788
 
 
789
      /* go to next field */
 
790
      fields++;
 
791
    }
 
792
    while ( 1 );
 
793
 
 
794
  Exit:
 
795
    /* close the frame if it was opened by this read */
 
796
    if ( frame_accessed )
 
797
      FT_Stream_ExitFrame( stream );
 
798
 
 
799
    return error;
 
800
  }
 
801
 
 
802
 
 
803
/* END */