~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/extras/freetype2/src/sfnt/ttcmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  ttcmap.c                                                               */
 
4
/*                                                                         */
 
5
/*    TrueType character mapping table (cmap) support (body).              */
 
6
/*                                                                         */
 
7
/*  Copyright 1996-2001, 2002 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_DEBUG_H
 
21
#include "ttload.h"
 
22
#include "ttcmap.h"
 
23
 
 
24
#include "sferrors.h"
 
25
 
 
26
 
 
27
  /*************************************************************************/
 
28
  /*                                                                       */
 
29
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
30
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
31
  /* messages during execution.                                            */
 
32
  /*                                                                       */
 
33
#undef  FT_COMPONENT
 
34
#define FT_COMPONENT  trace_ttcmap
 
35
 
 
36
 
 
37
  FT_CALLBACK_DEF( FT_UInt )
 
38
  code_to_index0( TT_CMapTable  charmap,
 
39
                  FT_ULong      char_code );
 
40
 
 
41
  FT_CALLBACK_DEF( FT_ULong )
 
42
  code_to_next0( TT_CMapTable  charmap,
 
43
                 FT_ULong      char_code );
 
44
 
 
45
  FT_CALLBACK_DEF( FT_UInt )
 
46
  code_to_index2( TT_CMapTable  charmap,
 
47
                  FT_ULong      char_code );
 
48
 
 
49
  FT_CALLBACK_DEF( FT_ULong )
 
50
  code_to_next2( TT_CMapTable  charmap,
 
51
                 FT_ULong      char_code );
 
52
 
 
53
  FT_CALLBACK_DEF( FT_UInt )
 
54
  code_to_index4( TT_CMapTable  charmap,
 
55
                  FT_ULong      char_code );
 
56
 
 
57
  FT_CALLBACK_DEF( FT_ULong )
 
58
  code_to_next4( TT_CMapTable  charmap,
 
59
                 FT_ULong      char_code );
 
60
 
 
61
  FT_CALLBACK_DEF( FT_UInt )
 
62
  code_to_index6( TT_CMapTable  charmap,
 
63
                  FT_ULong      char_code );
 
64
 
 
65
  FT_CALLBACK_DEF( FT_ULong )
 
66
  code_to_next6( TT_CMapTable  charmap,
 
67
                 FT_ULong      char_code );
 
68
 
 
69
  FT_CALLBACK_DEF( FT_UInt )
 
70
  code_to_index8_12( TT_CMapTable  charmap,
 
71
                     FT_ULong      char_code );
 
72
 
 
73
  FT_CALLBACK_DEF( FT_ULong )
 
74
  code_to_next8_12( TT_CMapTable  charmap,
 
75
                    FT_ULong      char_code );
 
76
 
 
77
  FT_CALLBACK_DEF( FT_UInt )
 
78
  code_to_index10( TT_CMapTable  charmap,
 
79
                   FT_ULong      char_code );
 
80
 
 
81
  FT_CALLBACK_DEF( FT_ULong )
 
82
  code_to_next10( TT_CMapTable  charmap,
 
83
                  FT_ULong      char_code );
 
84
 
 
85
 
 
86
  /*************************************************************************/
 
87
  /*                                                                       */
 
88
  /* <Function>                                                            */
 
89
  /*    TT_CharMap_Load                                                    */
 
90
  /*                                                                       */
 
91
  /* <Description>                                                         */
 
92
  /*    Loads a given TrueType character map into memory.                  */
 
93
  /*                                                                       */
 
94
  /* <Input>                                                               */
 
95
  /*    face   :: A handle to the parent face object.                      */
 
96
  /*                                                                       */
 
97
  /*    stream :: A handle to the current stream object.                   */
 
98
  /*                                                                       */
 
99
  /* <InOut>                                                               */
 
100
  /*    table  :: A pointer to a cmap object.                              */
 
101
  /*                                                                       */
 
102
  /* <Return>                                                              */
 
103
  /*    FreeType error code.  0 means success.                             */
 
104
  /*                                                                       */
 
105
  /* <Note>                                                                */
 
106
  /*    The function assumes that the stream is already in use (i.e.,      */
 
107
  /*    opened).  In case of error, all partially allocated tables are     */
 
108
  /*    released.                                                          */
 
109
  /*                                                                       */
 
110
  FT_LOCAL_DEF( FT_Error )
 
111
  TT_CharMap_Load( TT_Face       face,
 
112
                   TT_CMapTable  cmap,
 
113
                   FT_Stream     stream )
 
114
  {
 
115
    FT_Error     error;
 
116
    FT_Memory    memory;
 
117
    FT_UShort    num_SH, num_Seg, i;
 
118
    FT_ULong     j, n;
 
119
 
 
120
    FT_UShort    u, l;
 
121
 
 
122
    TT_CMap0     cmap0;
 
123
    TT_CMap2     cmap2;
 
124
    TT_CMap4     cmap4;
 
125
    TT_CMap6     cmap6;
 
126
    TT_CMap8_12  cmap8_12;
 
127
    TT_CMap10    cmap10;
 
128
 
 
129
    TT_CMap2SubHeader  cmap2sub;
 
130
    TT_CMap4Segment    segments;
 
131
    TT_CMapGroup       groups;
 
132
 
 
133
 
 
134
    if ( cmap->loaded )
 
135
      return SFNT_Err_Ok;
 
136
 
 
137
    memory = stream->memory;
 
138
 
 
139
    if ( FT_STREAM_SEEK( cmap->offset ) )
 
140
      return error;
 
141
 
 
142
    switch ( cmap->format )
 
143
    {
 
144
    case 0:
 
145
      cmap0 = &cmap->c.cmap0;
 
146
 
 
147
      if ( FT_READ_USHORT( cmap0->language )           ||
 
148
           FT_ALLOC( cmap0->glyphIdArray, 256L )       ||
 
149
           FT_STREAM_READ( cmap0->glyphIdArray, 256L ) )
 
150
        goto Fail;
 
151
 
 
152
      cmap->get_index     = code_to_index0;
 
153
      cmap->get_next_char = code_to_next0;
 
154
      break;
 
155
 
 
156
    case 2:
 
157
      num_SH = 0;
 
158
      cmap2  = &cmap->c.cmap2;
 
159
 
 
160
      /* allocate subheader keys */
 
161
 
 
162
      if ( FT_NEW_ARRAY( cmap2->subHeaderKeys, 256 ) ||
 
163
           FT_FRAME_ENTER( 2L + 512L )               )
 
164
        goto Fail;
 
165
 
 
166
      cmap2->language = FT_GET_USHORT();
 
167
 
 
168
      for ( i = 0; i < 256; i++ )
 
169
      {
 
170
        u = (FT_UShort)( FT_GET_USHORT() / 8 );
 
171
        cmap2->subHeaderKeys[i] = u;
 
172
 
 
173
        if ( num_SH < u )
 
174
          num_SH = u;
 
175
      }
 
176
 
 
177
      FT_FRAME_EXIT();
 
178
 
 
179
      /* load subheaders */
 
180
 
 
181
      cmap2->numGlyphId = l = (FT_UShort)(
 
182
        ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFFU ) / 2 );
 
183
 
 
184
      if ( FT_NEW_ARRAY( cmap2->subHeaders, num_SH + 1 ) ||
 
185
           FT_FRAME_ENTER( ( num_SH + 1 ) * 8L )         )
 
186
      {
 
187
        FT_FREE( cmap2->subHeaderKeys );
 
188
        goto Fail;
 
189
      }
 
190
 
 
191
      cmap2sub = cmap2->subHeaders;
 
192
 
 
193
      for ( i = 0; i <= num_SH; i++ )
 
194
      {
 
195
        cmap2sub->firstCode     = FT_GET_USHORT();
 
196
        cmap2sub->entryCount    = FT_GET_USHORT();
 
197
        cmap2sub->idDelta       = FT_GET_SHORT();
 
198
        /* we apply the location offset immediately */
 
199
        cmap2sub->idRangeOffset = (FT_UShort)(
 
200
          FT_GET_USHORT() - ( num_SH - i ) * 8 - 2 );
 
201
 
 
202
        cmap2sub++;
 
203
      }
 
204
 
 
205
      FT_FRAME_EXIT();
 
206
 
 
207
      /* load glyph IDs */
 
208
 
 
209
      if ( FT_NEW_ARRAY( cmap2->glyphIdArray, l ) ||
 
210
           FT_FRAME_ENTER( l * 2L )               )
 
211
      {
 
212
        FT_FREE( cmap2->subHeaders );
 
213
        FT_FREE( cmap2->subHeaderKeys );
 
214
        goto Fail;
 
215
      }
 
216
 
 
217
      for ( i = 0; i < l; i++ )
 
218
        cmap2->glyphIdArray[i] = FT_GET_USHORT();
 
219
 
 
220
      FT_FRAME_EXIT();
 
221
 
 
222
      cmap->get_index = code_to_index2;
 
223
      cmap->get_next_char = code_to_next2;
 
224
      break;
 
225
 
 
226
    case 4:
 
227
      cmap4 = &cmap->c.cmap4;
 
228
 
 
229
      /* load header */
 
230
 
 
231
      if ( FT_FRAME_ENTER( 10L ) )
 
232
        goto Fail;
 
233
 
 
234
      cmap4->language      = FT_GET_USHORT();
 
235
      cmap4->segCountX2    = FT_GET_USHORT();
 
236
      cmap4->searchRange   = FT_GET_USHORT();
 
237
      cmap4->entrySelector = FT_GET_USHORT();
 
238
      cmap4->rangeShift    = FT_GET_USHORT();
 
239
 
 
240
      num_Seg = (FT_UShort)( cmap4->segCountX2 / 2 );
 
241
 
 
242
      FT_FRAME_EXIT();
 
243
 
 
244
      /* load segments */
 
245
 
 
246
      if ( FT_NEW_ARRAY( cmap4->segments, num_Seg )   ||
 
247
           FT_FRAME_ENTER( ( num_Seg * 4 + 1 ) * 2L ) )
 
248
        goto Fail;
 
249
 
 
250
      segments = cmap4->segments;
 
251
 
 
252
      for ( i = 0; i < num_Seg; i++ )
 
253
        segments[i].endCount = FT_GET_USHORT();
 
254
 
 
255
      (void)FT_GET_USHORT();
 
256
 
 
257
      for ( i = 0; i < num_Seg; i++ )
 
258
        segments[i].startCount = FT_GET_USHORT();
 
259
 
 
260
      for ( i = 0; i < num_Seg; i++ )
 
261
        segments[i].idDelta = FT_GET_SHORT();
 
262
 
 
263
      for ( i = 0; i < num_Seg; i++ )
 
264
        segments[i].idRangeOffset = FT_GET_USHORT();
 
265
 
 
266
      FT_FRAME_EXIT();
 
267
 
 
268
      cmap4->numGlyphId = l = (FT_UShort)(
 
269
        ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFFU ) / 2 );
 
270
 
 
271
      /* load IDs */
 
272
 
 
273
      if ( FT_NEW_ARRAY( cmap4->glyphIdArray, l ) ||
 
274
           FT_FRAME_ENTER( l * 2L )               )
 
275
      {
 
276
        FT_FREE( cmap4->segments );
 
277
        goto Fail;
 
278
      }
 
279
 
 
280
      for ( i = 0; i < l; i++ )
 
281
        cmap4->glyphIdArray[i] = FT_GET_USHORT();
 
282
 
 
283
      FT_FRAME_EXIT();
 
284
 
 
285
      cmap4->last_segment = cmap4->segments;
 
286
 
 
287
      cmap->get_index     = code_to_index4;
 
288
      cmap->get_next_char = code_to_next4;
 
289
      break;
 
290
 
 
291
    case 6:
 
292
      cmap6 = &cmap->c.cmap6;
 
293
 
 
294
      if ( FT_FRAME_ENTER( 6L ) )
 
295
        goto Fail;
 
296
 
 
297
      cmap6->language   = FT_GET_USHORT();
 
298
      cmap6->firstCode  = FT_GET_USHORT();
 
299
      cmap6->entryCount = FT_GET_USHORT();
 
300
 
 
301
      FT_FRAME_EXIT();
 
302
 
 
303
      l = cmap6->entryCount;
 
304
 
 
305
      if ( FT_NEW_ARRAY( cmap6->glyphIdArray, l ) ||
 
306
           FT_FRAME_ENTER( l * 2L )               )
 
307
        goto Fail;
 
308
 
 
309
      for ( i = 0; i < l; i++ )
 
310
        cmap6->glyphIdArray[i] = FT_GET_USHORT();
 
311
 
 
312
      FT_FRAME_EXIT();
 
313
      cmap->get_index     = code_to_index6;
 
314
      cmap->get_next_char = code_to_next6;
 
315
      break;
 
316
 
 
317
    case 8:
 
318
    case 12:
 
319
      cmap8_12 = &cmap->c.cmap8_12;
 
320
 
 
321
      if ( FT_FRAME_ENTER( 8L ) )
 
322
        goto Fail;
 
323
 
 
324
      cmap->length       = FT_GET_ULONG();
 
325
      cmap8_12->language = FT_GET_ULONG();
 
326
 
 
327
      FT_FRAME_EXIT();
 
328
 
 
329
      if ( cmap->format == 8 )
 
330
        if ( FT_STREAM_SKIP( 8192L ) )
 
331
          goto Fail;
 
332
 
 
333
      if ( FT_READ_ULONG( cmap8_12->nGroups ) )
 
334
        goto Fail;
 
335
 
 
336
      n = cmap8_12->nGroups;
 
337
 
 
338
      if ( FT_NEW_ARRAY( cmap8_12->groups, n ) ||
 
339
           FT_FRAME_ENTER( n * 3 * 4L )        )
 
340
        goto Fail;
 
341
 
 
342
      groups = cmap8_12->groups;
 
343
 
 
344
      for ( j = 0; j < n; j++ )
 
345
      {
 
346
        groups[j].startCharCode = FT_GET_ULONG();
 
347
        groups[j].endCharCode   = FT_GET_ULONG();
 
348
        groups[j].startGlyphID  = FT_GET_ULONG();
 
349
      }
 
350
 
 
351
      FT_FRAME_EXIT();
 
352
 
 
353
      cmap8_12->last_group = cmap8_12->groups;
 
354
 
 
355
      cmap->get_index     = code_to_index8_12;
 
356
      cmap->get_next_char = code_to_next8_12;
 
357
      break;
 
358
 
 
359
    case 10:
 
360
      cmap10 = &cmap->c.cmap10;
 
361
 
 
362
      if ( FT_FRAME_ENTER( 16L ) )
 
363
        goto Fail;
 
364
 
 
365
      cmap->length          = FT_GET_ULONG();
 
366
      cmap10->language      = FT_GET_ULONG();
 
367
      cmap10->startCharCode = FT_GET_ULONG();
 
368
      cmap10->numChars      = FT_GET_ULONG();
 
369
 
 
370
      FT_FRAME_EXIT();
 
371
 
 
372
      n = cmap10->numChars;
 
373
 
 
374
      if ( FT_NEW_ARRAY( cmap10->glyphs, n ) ||
 
375
           FT_FRAME_ENTER( n * 2L )          )
 
376
        goto Fail;
 
377
 
 
378
      for ( j = 0; j < n; j++ )
 
379
        cmap10->glyphs[j] = FT_GET_USHORT();
 
380
 
 
381
      FT_FRAME_EXIT();
 
382
      cmap->get_index     = code_to_index10;
 
383
      cmap->get_next_char = code_to_next10;
 
384
      break;
 
385
 
 
386
    default:   /* corrupt character mapping table */
 
387
      return SFNT_Err_Invalid_CharMap_Format;
 
388
 
 
389
    }
 
390
 
 
391
    return SFNT_Err_Ok;
 
392
 
 
393
  Fail:
 
394
    TT_CharMap_Free( face, cmap );
 
395
    return error;
 
396
  }
 
397
 
 
398
 
 
399
  /*************************************************************************/
 
400
  /*                                                                       */
 
401
  /* <Function>                                                            */
 
402
  /*    TT_CharMap_Free                                                    */
 
403
  /*                                                                       */
 
404
  /* <Description>                                                         */
 
405
  /*    Destroys a character mapping table.                                */
 
406
  /*                                                                       */
 
407
  /* <Input>                                                               */
 
408
  /*    face :: A handle to the parent face object.                        */
 
409
  /*                                                                       */
 
410
  /*    cmap :: A handle to a cmap object.                                 */
 
411
  /*                                                                       */
 
412
  /* <Return>                                                              */
 
413
  /*    FreeType error code.  0 means success.                             */
 
414
  /*                                                                       */
 
415
  FT_LOCAL_DEF( FT_Error )
 
416
  TT_CharMap_Free( TT_Face       face,
 
417
                   TT_CMapTable  cmap )
 
418
  {
 
419
    FT_Memory  memory;
 
420
 
 
421
 
 
422
    if ( !cmap )
 
423
      return SFNT_Err_Ok;
 
424
 
 
425
    memory = face->root.driver->root.memory;
 
426
 
 
427
    switch ( cmap->format )
 
428
    {
 
429
    case 0:
 
430
      FT_FREE( cmap->c.cmap0.glyphIdArray );
 
431
      break;
 
432
 
 
433
    case 2:
 
434
      FT_FREE( cmap->c.cmap2.subHeaderKeys );
 
435
      FT_FREE( cmap->c.cmap2.subHeaders );
 
436
      FT_FREE( cmap->c.cmap2.glyphIdArray );
 
437
      break;
 
438
 
 
439
    case 4:
 
440
      FT_FREE( cmap->c.cmap4.segments );
 
441
      FT_FREE( cmap->c.cmap4.glyphIdArray );
 
442
      cmap->c.cmap4.segCountX2 = 0;
 
443
      break;
 
444
 
 
445
    case 6:
 
446
      FT_FREE( cmap->c.cmap6.glyphIdArray );
 
447
      cmap->c.cmap6.entryCount = 0;
 
448
      break;
 
449
 
 
450
    case 8:
 
451
    case 12:
 
452
      FT_FREE( cmap->c.cmap8_12.groups );
 
453
      cmap->c.cmap8_12.nGroups = 0;
 
454
      break;
 
455
 
 
456
    case 10:
 
457
      FT_FREE( cmap->c.cmap10.glyphs );
 
458
      cmap->c.cmap10.numChars = 0;
 
459
      break;
 
460
 
 
461
    default:
 
462
      /* invalid table format, do nothing */
 
463
      ;
 
464
    }
 
465
 
 
466
    cmap->loaded = FALSE;
 
467
    return SFNT_Err_Ok;
 
468
  }
 
469
 
 
470
 
 
471
  /*************************************************************************/
 
472
  /*                                                                       */
 
473
  /* <Function>                                                            */
 
474
  /*    code_to_index0                                                     */
 
475
  /*                                                                       */
 
476
  /* <Description>                                                         */
 
477
  /*    Converts the character code into a glyph index.  Uses format 0.    */
 
478
  /*    `charCode' must be in the range 0x00-0xFF (otherwise 0 is          */
 
479
  /*    returned).                                                         */
 
480
  /*                                                                       */
 
481
  /* <Input>                                                               */
 
482
  /*    charCode :: The wanted character code.                             */
 
483
  /*                                                                       */
 
484
  /*    cmap0    :: A pointer to a cmap table in format 0.                 */
 
485
  /*                                                                       */
 
486
  /* <Return>                                                              */
 
487
  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
 
488
  /*                                                                       */
 
489
  FT_CALLBACK_DEF( FT_UInt )
 
490
  code_to_index0( TT_CMapTable  cmap,
 
491
                  FT_ULong      charCode )
 
492
  {
 
493
    TT_CMap0  cmap0 = &cmap->c.cmap0;
 
494
 
 
495
 
 
496
    return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 );
 
497
  }
 
498
 
 
499
 
 
500
  /*************************************************************************/
 
501
  /*                                                                       */
 
502
  /* <Function>                                                            */
 
503
  /*    code_to_next0                                                      */
 
504
  /*                                                                       */
 
505
  /* <Description>                                                         */
 
506
  /*    Finds the next encoded character after the given one.  Uses        */
 
507
  /*    format 0. `charCode' must be in the range 0x00-0xFF (otherwise 0   */
 
508
  /*    is returned).                                                      */
 
509
  /*                                                                       */
 
510
  /* <Input>                                                               */
 
511
  /*    charCode :: The wanted character code.                             */
 
512
  /*                                                                       */
 
513
  /*    cmap0    :: A pointer to a cmap table in format 0.                 */
 
514
  /*                                                                       */
 
515
  /* <Return>                                                              */
 
516
  /*    Next char code.  0 if no higher one is encoded.                    */
 
517
  /*                                                                       */
 
518
  FT_CALLBACK_DEF( FT_ULong )
 
519
  code_to_next0( TT_CMapTable  cmap,
 
520
                 FT_ULong      charCode )
 
521
  {
 
522
    TT_CMap0  cmap0 = &cmap->c.cmap0;
 
523
 
 
524
 
 
525
    while ( ++charCode <= 0xFF )
 
526
      if ( cmap0->glyphIdArray[charCode] )
 
527
        return ( charCode );
 
528
    return ( 0 );
 
529
  }
 
530
 
 
531
 
 
532
  /*************************************************************************/
 
533
  /*                                                                       */
 
534
  /* <Function>                                                            */
 
535
  /*    code_to_index2                                                     */
 
536
  /*                                                                       */
 
537
  /* <Description>                                                         */
 
538
  /*    Converts the character code into a glyph index.  Uses format 2.    */
 
539
  /*                                                                       */
 
540
  /* <Input>                                                               */
 
541
  /*    charCode :: The wanted character code.                             */
 
542
  /*                                                                       */
 
543
  /*    cmap2    :: A pointer to a cmap table in format 2.                 */
 
544
  /*                                                                       */
 
545
  /* <Return>                                                              */
 
546
  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
 
547
  /*                                                                       */
 
548
  FT_CALLBACK_DEF( FT_UInt )
 
549
  code_to_index2( TT_CMapTable  cmap,
 
550
                  FT_ULong      charCode )
 
551
  {
 
552
    FT_UInt            result, index1, offset;
 
553
    FT_UInt            char_lo;
 
554
    FT_ULong           char_hi;
 
555
    TT_CMap2SubHeader  sh2;
 
556
    TT_CMap2           cmap2;
 
557
 
 
558
 
 
559
    cmap2   = &cmap->c.cmap2;
 
560
    result  = 0;
 
561
    char_lo = (FT_UInt)( charCode & 0xFF );
 
562
    char_hi = charCode >> 8;
 
563
 
 
564
    if ( char_hi == 0 )
 
565
    {
 
566
      /* an 8-bit character code -- we use the subHeader 0 in this case */
 
567
      /* to test whether the character code is in the charmap           */
 
568
      index1 = cmap2->subHeaderKeys[char_lo];
 
569
      if ( index1 != 0 )
 
570
        return 0;
 
571
    }
 
572
    else
 
573
    {
 
574
      /* a 16-bit character code */
 
575
      index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
 
576
      if ( index1 == 0 )
 
577
        return 0;
 
578
    }
 
579
 
 
580
    sh2      = cmap2->subHeaders + index1;
 
581
    char_lo -= sh2->firstCode;
 
582
 
 
583
    if ( char_lo < (FT_UInt)sh2->entryCount )
 
584
    {
 
585
      offset = sh2->idRangeOffset / 2 + char_lo;
 
586
      if ( offset < (FT_UInt)cmap2->numGlyphId )
 
587
      {
 
588
        result = cmap2->glyphIdArray[offset];
 
589
        if ( result )
 
590
          result = ( result + sh2->idDelta ) & 0xFFFFU;
 
591
      }
 
592
    }
 
593
 
 
594
    return result;
 
595
  }
 
596
 
 
597
 
 
598
  /*************************************************************************/
 
599
  /*                                                                       */
 
600
  /* <Function>                                                            */
 
601
  /*    code_to_next2                                                      */
 
602
  /*                                                                       */
 
603
  /* <Description>                                                         */
 
604
  /*    Find the next encoded character.  Uses format 2.                   */
 
605
  /*                                                                       */
 
606
  /* <Input>                                                               */
 
607
  /*    charCode :: The wanted character code.                             */
 
608
  /*                                                                       */
 
609
  /*    cmap2    :: A pointer to a cmap table in format 2.                 */
 
610
  /*                                                                       */
 
611
  /* <Return>                                                              */
 
612
  /*    Next encoded character.  0 if none exists.                         */
 
613
  /*                                                                       */
 
614
  FT_CALLBACK_DEF( FT_ULong )
 
615
  code_to_next2( TT_CMapTable  cmap,
 
616
                 FT_ULong      charCode )
 
617
  {
 
618
    FT_UInt            index1, offset;
 
619
    FT_UInt            char_lo;
 
620
    FT_ULong           char_hi;
 
621
    TT_CMap2SubHeader  sh2;
 
622
    TT_CMap2           cmap2;
 
623
 
 
624
 
 
625
    cmap2 = &cmap->c.cmap2;
 
626
    charCode++;
 
627
 
 
628
    /*
 
629
     * This is relatively simplistic -- look for a subHeader containing
 
630
     * glyphs and then walk to the first glyph in that subHeader.
 
631
     */
 
632
    while ( charCode < 0x10000 )
 
633
    {
 
634
      char_lo = (FT_UInt)( charCode & 0xFF );
 
635
      char_hi = charCode >> 8;
 
636
  
 
637
      if ( char_hi == 0 )
 
638
      {
 
639
        /* an 8-bit character code -- we use the subHeader 0 in this case */
 
640
        /* to test whether the character code is in the charmap           */
 
641
        index1 = cmap2->subHeaderKeys[char_lo];
 
642
        if ( index1 != 0 )
 
643
        {
 
644
          charCode++;
 
645
          continue;
 
646
        }
 
647
      }
 
648
      else
 
649
      {
 
650
        /* a 16-bit character code */
 
651
        index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
 
652
        if ( index1 == 0 )
 
653
        {
 
654
          charCode = ( char_hi + 1 ) << 8;
 
655
          continue;
 
656
        }
 
657
      }
 
658
  
 
659
      sh2      = cmap2->subHeaders + index1;
 
660
      char_lo -= sh2->firstCode;
 
661
  
 
662
      if ( char_lo > (FT_UInt)sh2->entryCount )
 
663
      {
 
664
        charCode = ( char_hi + 1 ) << 8;
 
665
        continue;
 
666
      }
 
667
      
 
668
      offset = sh2->idRangeOffset / 2 + char_lo;
 
669
      if ( offset >= (FT_UInt)cmap2->numGlyphId ||
 
670
           cmap2->glyphIdArray[offset] == 0     )
 
671
      {
 
672
        charCode++;
 
673
        continue;
 
674
      }
 
675
      
 
676
      return charCode;
 
677
    }
 
678
    return 0;
 
679
  }
 
680
 
 
681
 
 
682
  /*************************************************************************/
 
683
  /*                                                                       */
 
684
  /* <Function>                                                            */
 
685
  /*    code_to_index4                                                     */
 
686
  /*                                                                       */
 
687
  /* <Description>                                                         */
 
688
  /*    Converts the character code into a glyph index.  Uses format 4.    */
 
689
  /*                                                                       */
 
690
  /* <Input>                                                               */
 
691
  /*    charCode :: The wanted character code.                             */
 
692
  /*                                                                       */
 
693
  /*    cmap4    :: A pointer to a cmap table in format 4.                 */
 
694
  /*                                                                       */
 
695
  /* <Return>                                                              */
 
696
  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
 
697
  /*                                                                       */
 
698
  FT_CALLBACK_DEF( FT_UInt )
 
699
  code_to_index4( TT_CMapTable  cmap,
 
700
                  FT_ULong      charCode )
 
701
  {
 
702
    FT_UInt             result, index1, segCount;
 
703
    TT_CMap4            cmap4;
 
704
    TT_CMap4SegmentRec  *seg4, *limit;
 
705
 
 
706
 
 
707
    cmap4    = &cmap->c.cmap4;
 
708
    result   = 0;
 
709
    segCount = cmap4->segCountX2 / 2;
 
710
    limit    = cmap4->segments + segCount;
 
711
 
 
712
    /* first, check against the last used segment */
 
713
 
 
714
    seg4 = cmap4->last_segment;
 
715
 
 
716
    /* the following is equivalent to performing two tests, as in         */
 
717
    /*                                                                    */
 
718
    /*  if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */
 
719
    /*                                                                    */
 
720
    /* This is a bit strange, but it is faster, and the idea behind the   */
 
721
    /* cache is to significantly speed up charcode to glyph index         */
 
722
    /* conversion.                                                        */
 
723
 
 
724
    if ( (FT_ULong)( charCode       - seg4->startCount ) <
 
725
         (FT_ULong)( seg4->endCount - seg4->startCount ) )
 
726
      goto Found1;
 
727
 
 
728
    for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
 
729
    {
 
730
      /* the ranges are sorted in increasing order.  If we are out of */
 
731
      /* the range here, the char code isn't in the charmap, so exit. */
 
732
 
 
733
      if ( charCode > (FT_UInt)seg4->endCount )
 
734
        continue;
 
735
 
 
736
      if ( charCode >= (FT_UInt)seg4->startCount )
 
737
        goto Found;
 
738
    }
 
739
    return 0;
 
740
 
 
741
  Found:
 
742
    cmap4->last_segment = seg4;
 
743
 
 
744
  Found1:
 
745
    /* if the idRangeOffset is 0, we can compute the glyph index */
 
746
    /* directly                                                  */
 
747
 
 
748
    if ( seg4->idRangeOffset == 0 )
 
749
      result = ( charCode + seg4->idDelta ) & 0xFFFFU;
 
750
    else
 
751
    {
 
752
      /* otherwise, we must use the glyphIdArray to do it */
 
753
      index1 = (FT_UInt)( seg4->idRangeOffset / 2
 
754
                          + ( charCode - seg4->startCount )
 
755
                          + ( seg4 - cmap4->segments )
 
756
                          - segCount );
 
757
 
 
758
      if ( index1 < (FT_UInt)cmap4->numGlyphId &&
 
759
           cmap4->glyphIdArray[index1] != 0    )
 
760
        result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFFU;
 
761
    }
 
762
 
 
763
    return result;
 
764
  }
 
765
 
 
766
 
 
767
  /*************************************************************************/
 
768
  /*                                                                       */
 
769
  /* <Function>                                                            */
 
770
  /*    code_to_next4                                                      */
 
771
  /*                                                                       */
 
772
  /* <Description>                                                         */
 
773
  /*    Find the next encoded character.  Uses format 4.                   */
 
774
  /*                                                                       */
 
775
  /* <Input>                                                               */
 
776
  /*    charCode :: The wanted character code.                             */
 
777
  /*                                                                       */
 
778
  /*    cmap     :: A pointer to a cmap table in format 4.                 */
 
779
  /*                                                                       */
 
780
  /* <Return>                                                              */
 
781
  /*    Next encoded character.  0 if none exists.                         */
 
782
  /*                                                                       */
 
783
  FT_CALLBACK_DEF( FT_ULong )
 
784
  code_to_next4( TT_CMapTable  cmap,
 
785
                 FT_ULong      charCode )
 
786
  {
 
787
    FT_UInt             index1, segCount;
 
788
    TT_CMap4            cmap4;
 
789
    TT_CMap4SegmentRec  *seg4, *limit;
 
790
 
 
791
 
 
792
    cmap4    = &cmap->c.cmap4;
 
793
    segCount = cmap4->segCountX2 / 2;
 
794
    limit    = cmap4->segments + segCount;
 
795
 
 
796
    charCode++;
 
797
 
 
798
    for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
 
799
    {
 
800
      /* The ranges are sorted in increasing order.  If we are out of */
 
801
      /* the range here, the char code isn't in the charmap, so exit. */
 
802
 
 
803
      if ( charCode <= (FT_UInt)seg4->endCount )
 
804
        goto Found;
 
805
    }
 
806
    return 0;
 
807
 
 
808
  Found:
 
809
    if ( charCode < (FT_ULong) seg4->startCount )
 
810
      charCode = seg4->startCount;
 
811
 
 
812
    /* if the idRangeOffset is 0, all chars in the map exist */
 
813
 
 
814
    if ( seg4->idRangeOffset == 0 )
 
815
      return ( charCode );
 
816
    
 
817
    while ( charCode <= (FT_UInt) seg4->endCount )
 
818
    {
 
819
      /* otherwise, we must use the glyphIdArray to do it */
 
820
      index1 = (FT_UInt)( seg4->idRangeOffset / 2
 
821
                          + ( charCode - seg4->startCount )
 
822
                          + ( seg4 - cmap4->segments )
 
823
                          - segCount );
 
824
 
 
825
      if ( index1 < (FT_UInt)cmap4->numGlyphId &&
 
826
           cmap4->glyphIdArray[index1] != 0    )
 
827
        return ( charCode );
 
828
      charCode++;
 
829
    }
 
830
 
 
831
    return 0;
 
832
  }
 
833
 
 
834
 
 
835
  /*************************************************************************/
 
836
  /*                                                                       */
 
837
  /* <Function>                                                            */
 
838
  /*    code_to_index6                                                     */
 
839
  /*                                                                       */
 
840
  /* <Description>                                                         */
 
841
  /*    Converts the character code into a glyph index.  Uses format 6.    */
 
842
  /*                                                                       */
 
843
  /* <Input>                                                               */
 
844
  /*    charCode :: The wanted character code.                             */
 
845
  /*                                                                       */
 
846
  /*    cmap6    :: A pointer to a cmap table in format 6.                 */
 
847
  /*                                                                       */
 
848
  /* <Return>                                                              */
 
849
  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
 
850
  /*                                                                       */
 
851
  FT_CALLBACK_DEF( FT_UInt )
 
852
  code_to_index6( TT_CMapTable  cmap,
 
853
                  FT_ULong      charCode )
 
854
  {
 
855
    TT_CMap6  cmap6;
 
856
    FT_UInt   result = 0;
 
857
 
 
858
 
 
859
    cmap6     = &cmap->c.cmap6;
 
860
    charCode -= cmap6->firstCode;
 
861
 
 
862
    if ( charCode < (FT_UInt)cmap6->entryCount )
 
863
      result = cmap6->glyphIdArray[charCode];
 
864
 
 
865
    return result;
 
866
  }
 
867
 
 
868
 
 
869
  /*************************************************************************/
 
870
  /*                                                                       */
 
871
  /* <Function>                                                            */
 
872
  /*    code_to_next6                                                      */
 
873
  /*                                                                       */
 
874
  /* <Description>                                                         */
 
875
  /*    Find the next encoded character.  Uses format 6.                   */
 
876
  /*                                                                       */
 
877
  /* <Input>                                                               */
 
878
  /*    charCode :: The wanted character code.                             */
 
879
  /*                                                                       */
 
880
  /*    cmap     :: A pointer to a cmap table in format 6.                 */
 
881
  /*                                                                       */
 
882
  /* <Return>                                                              */
 
883
  /*    Next encoded character.  0 if none exists.                         */
 
884
  /*                                                                       */
 
885
  FT_CALLBACK_DEF( FT_ULong )
 
886
  code_to_next6( TT_CMapTable  cmap,
 
887
                 FT_ULong      charCode )
 
888
  {
 
889
    TT_CMap6  cmap6;
 
890
 
 
891
 
 
892
    charCode++;
 
893
    
 
894
    cmap6 = &cmap->c.cmap6;
 
895
    
 
896
    if ( charCode < (FT_ULong) cmap6->firstCode )
 
897
      charCode = cmap6->firstCode;
 
898
    
 
899
    charCode -= cmap6->firstCode;
 
900
 
 
901
    while ( charCode < (FT_UInt)cmap6->entryCount )
 
902
    {
 
903
      if ( cmap6->glyphIdArray[charCode] != 0 )
 
904
        return charCode + cmap6->firstCode;
 
905
      charCode++;
 
906
    }
 
907
 
 
908
    return 0;
 
909
  }
 
910
 
 
911
 
 
912
  /*************************************************************************/
 
913
  /*                                                                       */
 
914
  /* <Function>                                                            */
 
915
  /*    code_to_index8_12                                                  */
 
916
  /*                                                                       */
 
917
  /* <Description>                                                         */
 
918
  /*    Converts the (possibly 32bit) character code into a glyph index.   */
 
919
  /*    Uses format 8 or 12.                                               */
 
920
  /*                                                                       */
 
921
  /* <Input>                                                               */
 
922
  /*    charCode :: The wanted character code.                             */
 
923
  /*                                                                       */
 
924
  /*    cmap8_12 :: A pointer to a cmap table in format 8 or 12.           */
 
925
  /*                                                                       */
 
926
  /* <Return>                                                              */
 
927
  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
 
928
  /*                                                                       */
 
929
  FT_CALLBACK_DEF( FT_UInt )
 
930
  code_to_index8_12( TT_CMapTable  cmap,
 
931
                     FT_ULong      charCode )
 
932
  {
 
933
    TT_CMap8_12      cmap8_12;
 
934
    TT_CMapGroupRec  *group, *limit;
 
935
 
 
936
 
 
937
    cmap8_12 = &cmap->c.cmap8_12;
 
938
    limit    = cmap8_12->groups + cmap8_12->nGroups;
 
939
 
 
940
    /* first, check against the last used group */
 
941
 
 
942
    group = cmap8_12->last_group;
 
943
 
 
944
    /* the following is equivalent to performing two tests, as in       */
 
945
    /*                                                                  */
 
946
    /*  if ( charCode >= group->startCharCode &&                        */
 
947
    /*       charCode <= group->endCharCode   )                         */
 
948
    /*                                                                  */
 
949
    /* This is a bit strange, but it is faster, and the idea behind the */
 
950
    /* cache is to significantly speed up charcode to glyph index       */
 
951
    /* conversion.                                                      */
 
952
 
 
953
    if ( (FT_ULong)( charCode           - group->startCharCode ) <
 
954
         (FT_ULong)( group->endCharCode - group->startCharCode ) )
 
955
      goto Found1;
 
956
 
 
957
    for ( group = cmap8_12->groups; group < limit; group++ )
 
958
    {
 
959
      /* the ranges are sorted in increasing order.  If we are out of */
 
960
      /* the range here, the char code isn't in the charmap, so exit. */
 
961
 
 
962
      if ( charCode > group->endCharCode )
 
963
        continue;
 
964
 
 
965
      if ( charCode >= group->startCharCode )
 
966
        goto Found;
 
967
    }
 
968
    return 0;
 
969
 
 
970
  Found:
 
971
    cmap8_12->last_group = group;
 
972
 
 
973
  Found1:
 
974
    return group->startGlyphID + (FT_UInt)( charCode - group->startCharCode );
 
975
  }
 
976
 
 
977
 
 
978
  /*************************************************************************/
 
979
  /*                                                                       */
 
980
  /* <Function>                                                            */
 
981
  /*    code_to_next8_12                                                   */
 
982
  /*                                                                       */
 
983
  /* <Description>                                                         */
 
984
  /*    Find the next encoded character.  Uses format 8 or 12.             */
 
985
  /*                                                                       */
 
986
  /* <Input>                                                               */
 
987
  /*    charCode :: The wanted character code.                             */
 
988
  /*                                                                       */
 
989
  /*    cmap     :: A pointer to a cmap table in format 8 or 12.           */
 
990
  /*                                                                       */
 
991
  /* <Return>                                                              */
 
992
  /*    Next encoded character.  0 if none exists.                         */
 
993
  /*                                                                       */
 
994
  FT_CALLBACK_DEF( FT_ULong )
 
995
  code_to_next8_12( TT_CMapTable  cmap,
 
996
                    FT_ULong      charCode )
 
997
  {
 
998
    TT_CMap8_12      cmap8_12;
 
999
    TT_CMapGroupRec  *group, *limit;
 
1000
 
 
1001
 
 
1002
    charCode++;
 
1003
    cmap8_12 = &cmap->c.cmap8_12;
 
1004
    limit    = cmap8_12->groups + cmap8_12->nGroups;
 
1005
 
 
1006
    for ( group = cmap8_12->groups; group < limit; group++ )
 
1007
    {
 
1008
      /* the ranges are sorted in increasing order.  If we are out of */
 
1009
      /* the range here, the char code isn't in the charmap, so exit. */
 
1010
 
 
1011
      if ( charCode <= group->endCharCode )
 
1012
        goto Found;
 
1013
    }
 
1014
    return 0;
 
1015
 
 
1016
  Found:
 
1017
    if ( charCode < group->startCharCode )
 
1018
      charCode = group->startCharCode;
 
1019
    
 
1020
    return charCode;
 
1021
  }
 
1022
 
 
1023
 
 
1024
  /*************************************************************************/
 
1025
  /*                                                                       */
 
1026
  /* <Function>                                                            */
 
1027
  /*    code_to_index10                                                    */
 
1028
  /*                                                                       */
 
1029
  /* <Description>                                                         */
 
1030
  /*    Converts the (possibly 32bit) character code into a glyph index.   */
 
1031
  /*    Uses format 10.                                                    */
 
1032
  /*                                                                       */
 
1033
  /* <Input>                                                               */
 
1034
  /*    charCode :: The wanted character code.                             */
 
1035
  /*                                                                       */
 
1036
  /*    cmap10   :: A pointer to a cmap table in format 10.                */
 
1037
  /*                                                                       */
 
1038
  /* <Return>                                                              */
 
1039
  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
 
1040
  /*                                                                       */
 
1041
  FT_CALLBACK_DEF( FT_UInt )
 
1042
  code_to_index10( TT_CMapTable  cmap,
 
1043
                   FT_ULong      charCode )
 
1044
  {
 
1045
    TT_CMap10  cmap10;
 
1046
    FT_UInt    result = 0;
 
1047
 
 
1048
 
 
1049
    cmap10    = &cmap->c.cmap10;
 
1050
    charCode -= cmap10->startCharCode;
 
1051
 
 
1052
    /* the overflow trick for comparison works here also since the number */
 
1053
    /* of glyphs (even if numChars is specified as ULong in the specs) in */
 
1054
    /* an OpenType font is limited to 64k                                 */
 
1055
 
 
1056
    if ( charCode < cmap10->numChars )
 
1057
      result = cmap10->glyphs[charCode];
 
1058
 
 
1059
    return result;
 
1060
  }
 
1061
 
 
1062
 
 
1063
  /*************************************************************************/
 
1064
  /*                                                                       */
 
1065
  /* <Function>                                                            */
 
1066
  /*    code_to_next10                                                     */
 
1067
  /*                                                                       */
 
1068
  /* <Description>                                                         */
 
1069
  /*    Find the next encoded character.  Uses format 10.                  */
 
1070
  /*                                                                       */
 
1071
  /* <Input>                                                               */
 
1072
  /*    charCode :: The wanted character code.                             */
 
1073
  /*                                                                       */
 
1074
  /*    cmap     :: A pointer to a cmap table in format 10.                */
 
1075
  /*                                                                       */
 
1076
  /* <Return>                                                              */
 
1077
  /*    Next encoded character.  0 if none exists.                         */
 
1078
  /*                                                                       */
 
1079
  FT_CALLBACK_DEF( FT_ULong )
 
1080
  code_to_next10( TT_CMapTable  cmap,
 
1081
                  FT_ULong      charCode )
 
1082
  {
 
1083
    TT_CMap10  cmap10;
 
1084
 
 
1085
 
 
1086
    charCode++;
 
1087
    cmap10 = &cmap->c.cmap10;
 
1088
    
 
1089
    if ( charCode < cmap10->startCharCode )
 
1090
      charCode = cmap10->startCharCode;
 
1091
    
 
1092
    charCode -= cmap10->startCharCode;
 
1093
 
 
1094
    /* the overflow trick for comparison works here also since the number */
 
1095
    /* of glyphs (even if numChars is specified as ULong in the specs) in */
 
1096
    /* an OpenType font is limited to 64k                                 */
 
1097
 
 
1098
    while ( charCode < cmap10->numChars )
 
1099
    {
 
1100
      if ( cmap10->glyphs[charCode] )
 
1101
        return ( charCode + cmap10->startCharCode );
 
1102
      charCode++;
 
1103
    }
 
1104
 
 
1105
    return 0;
 
1106
  }
 
1107
 
 
1108
 
 
1109
/* END */