xref: /inferno-os/libfreetype/ttcmap0.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ttcmap0.c                                                              */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    TrueType new character mapping table (cmap) support (body).          */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 2002 by                                                      */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include <ft2build.h>
20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
21*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
22*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
23*37da2899SCharles.Forsyth #include "ttload.h"
24*37da2899SCharles.Forsyth #include "ttcmap0.h"
25*37da2899SCharles.Forsyth 
26*37da2899SCharles.Forsyth #include "sferrors.h"
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth   /*************************************************************************/
29*37da2899SCharles.Forsyth   /*                                                                       */
30*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
31*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
32*37da2899SCharles.Forsyth   /* messages during execution.                                            */
33*37da2899SCharles.Forsyth   /*                                                                       */
34*37da2899SCharles.Forsyth #undef  FT_COMPONENT
35*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_ttcmap
36*37da2899SCharles.Forsyth 
37*37da2899SCharles.Forsyth 
38*37da2899SCharles.Forsyth #define TT_PEEK_SHORT   FT_PEEK_SHORT
39*37da2899SCharles.Forsyth #define TT_PEEK_USHORT  FT_PEEK_USHORT
40*37da2899SCharles.Forsyth #define TT_PEEK_LONG    FT_PEEK_LONG
41*37da2899SCharles.Forsyth #define TT_PEEK_ULONG   FT_PEEK_ULONG
42*37da2899SCharles.Forsyth 
43*37da2899SCharles.Forsyth #define TT_NEXT_SHORT   FT_NEXT_SHORT
44*37da2899SCharles.Forsyth #define TT_NEXT_USHORT  FT_NEXT_USHORT
45*37da2899SCharles.Forsyth #define TT_NEXT_LONG    FT_NEXT_LONG
46*37da2899SCharles.Forsyth #define TT_NEXT_ULONG   FT_NEXT_ULONG
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Error )
tt_cmap_init(TT_CMap cmap,FT_Byte * table)50*37da2899SCharles.Forsyth   tt_cmap_init( TT_CMap   cmap,
51*37da2899SCharles.Forsyth                 FT_Byte*  table )
52*37da2899SCharles.Forsyth   {
53*37da2899SCharles.Forsyth     cmap->data = table;
54*37da2899SCharles.Forsyth     return 0;
55*37da2899SCharles.Forsyth   }
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth 
58*37da2899SCharles.Forsyth   /*************************************************************************/
59*37da2899SCharles.Forsyth   /*************************************************************************/
60*37da2899SCharles.Forsyth   /*****                                                               *****/
61*37da2899SCharles.Forsyth   /*****                           FORMAT 0                            *****/
62*37da2899SCharles.Forsyth   /*****                                                               *****/
63*37da2899SCharles.Forsyth   /*************************************************************************/
64*37da2899SCharles.Forsyth   /*************************************************************************/
65*37da2899SCharles.Forsyth 
66*37da2899SCharles.Forsyth   /*************************************************************************/
67*37da2899SCharles.Forsyth   /*                                                                       */
68*37da2899SCharles.Forsyth   /* TABLE OVERVIEW                                                        */
69*37da2899SCharles.Forsyth   /* --------------                                                        */
70*37da2899SCharles.Forsyth   /*                                                                       */
71*37da2899SCharles.Forsyth   /*   NAME        OFFSET         TYPE          DESCRIPTION                */
72*37da2899SCharles.Forsyth   /*                                                                       */
73*37da2899SCharles.Forsyth   /*   format      0              USHORT        must be 0                  */
74*37da2899SCharles.Forsyth   /*   length      2              USHORT        table length in bytes      */
75*37da2899SCharles.Forsyth   /*   language    4              USHORT        Mac language code          */
76*37da2899SCharles.Forsyth   /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
77*37da2899SCharles.Forsyth   /*               262                                                     */
78*37da2899SCharles.Forsyth   /*                                                                       */
79*37da2899SCharles.Forsyth 
80*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_0
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
tt_cmap0_validate(FT_Byte * table,FT_Validator valid)83*37da2899SCharles.Forsyth   tt_cmap0_validate( FT_Byte*      table,
84*37da2899SCharles.Forsyth                      FT_Validator  valid )
85*37da2899SCharles.Forsyth   {
86*37da2899SCharles.Forsyth     FT_Byte*  p      = table + 2;
87*37da2899SCharles.Forsyth     FT_UInt   length = TT_NEXT_USHORT( p );
88*37da2899SCharles.Forsyth 
89*37da2899SCharles.Forsyth 
90*37da2899SCharles.Forsyth     if ( table + length > valid->limit || length < 262 )
91*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
92*37da2899SCharles.Forsyth 
93*37da2899SCharles.Forsyth     /* check glyph indices whenever necessary */
94*37da2899SCharles.Forsyth     if ( valid->level >= FT_VALIDATE_TIGHT )
95*37da2899SCharles.Forsyth     {
96*37da2899SCharles.Forsyth       FT_UInt  n, idx;
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth       p = table + 6;
100*37da2899SCharles.Forsyth       for ( n = 0; n < 256; n++ )
101*37da2899SCharles.Forsyth       {
102*37da2899SCharles.Forsyth         idx = *p++;
103*37da2899SCharles.Forsyth         if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
104*37da2899SCharles.Forsyth           FT_INVALID_GLYPH_ID;
105*37da2899SCharles.Forsyth       }
106*37da2899SCharles.Forsyth     }
107*37da2899SCharles.Forsyth   }
108*37da2899SCharles.Forsyth 
109*37da2899SCharles.Forsyth 
110*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap0_char_index(TT_CMap cmap,FT_UInt32 char_code)111*37da2899SCharles.Forsyth   tt_cmap0_char_index( TT_CMap    cmap,
112*37da2899SCharles.Forsyth                        FT_UInt32  char_code )
113*37da2899SCharles.Forsyth   {
114*37da2899SCharles.Forsyth     FT_Byte*  table = cmap->data;
115*37da2899SCharles.Forsyth 
116*37da2899SCharles.Forsyth 
117*37da2899SCharles.Forsyth     return char_code < 256 ? table[6 + char_code] : 0;
118*37da2899SCharles.Forsyth   }
119*37da2899SCharles.Forsyth 
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap0_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)122*37da2899SCharles.Forsyth   tt_cmap0_char_next( TT_CMap     cmap,
123*37da2899SCharles.Forsyth                       FT_UInt32  *pchar_code )
124*37da2899SCharles.Forsyth   {
125*37da2899SCharles.Forsyth     FT_Byte*   table    = cmap->data;
126*37da2899SCharles.Forsyth     FT_UInt32  charcode = *pchar_code;
127*37da2899SCharles.Forsyth     FT_UInt32  result   = 0;
128*37da2899SCharles.Forsyth     FT_UInt    gindex   = 0;
129*37da2899SCharles.Forsyth 
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth     table += 6;  /* go to glyph ids */
132*37da2899SCharles.Forsyth     while ( ++charcode < 256 )
133*37da2899SCharles.Forsyth     {
134*37da2899SCharles.Forsyth       gindex = table[charcode];
135*37da2899SCharles.Forsyth       if ( gindex != 0 )
136*37da2899SCharles.Forsyth       {
137*37da2899SCharles.Forsyth         result = charcode;
138*37da2899SCharles.Forsyth         break;
139*37da2899SCharles.Forsyth       }
140*37da2899SCharles.Forsyth     }
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth     *pchar_code = result;
143*37da2899SCharles.Forsyth     return gindex;
144*37da2899SCharles.Forsyth   }
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth 
147*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
148*37da2899SCharles.Forsyth   const TT_CMap_ClassRec  tt_cmap0_class_rec =
149*37da2899SCharles.Forsyth   {
150*37da2899SCharles.Forsyth     {
151*37da2899SCharles.Forsyth       sizeof( TT_CMapRec ),
152*37da2899SCharles.Forsyth 
153*37da2899SCharles.Forsyth       (FT_CMap_InitFunc)     tt_cmap_init,
154*37da2899SCharles.Forsyth       (FT_CMap_DoneFunc)     NULL,
155*37da2899SCharles.Forsyth       (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
156*37da2899SCharles.Forsyth       (FT_CMap_CharNextFunc) tt_cmap0_char_next
157*37da2899SCharles.Forsyth     },
158*37da2899SCharles.Forsyth     0,
159*37da2899SCharles.Forsyth     (TT_CMap_ValidateFunc)   tt_cmap0_validate
160*37da2899SCharles.Forsyth   };
161*37da2899SCharles.Forsyth 
162*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_0 */
163*37da2899SCharles.Forsyth 
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth   /*************************************************************************/
166*37da2899SCharles.Forsyth   /*************************************************************************/
167*37da2899SCharles.Forsyth   /*****                                                               *****/
168*37da2899SCharles.Forsyth   /*****                          FORMAT 2                             *****/
169*37da2899SCharles.Forsyth   /*****                                                               *****/
170*37da2899SCharles.Forsyth   /***** This is used for certain CJK encodings that encode text in a  *****/
171*37da2899SCharles.Forsyth   /***** mixed 8/16 bits encoding along the following lines:           *****/
172*37da2899SCharles.Forsyth   /*****                                                               *****/
173*37da2899SCharles.Forsyth   /***** * Certain byte values correspond to an 8-bit character code   *****/
174*37da2899SCharles.Forsyth   /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
175*37da2899SCharles.Forsyth   /*****                                                               *****/
176*37da2899SCharles.Forsyth   /***** * Certain byte values signal the first byte of a 2-byte       *****/
177*37da2899SCharles.Forsyth   /*****   character code (but these values are also valid as the      *****/
178*37da2899SCharles.Forsyth   /*****   second byte of a 2-byte character).                         *****/
179*37da2899SCharles.Forsyth   /*****                                                               *****/
180*37da2899SCharles.Forsyth   /***** The following charmap lookup and iteration functions all      *****/
181*37da2899SCharles.Forsyth   /***** assume that the value "charcode" correspond to following:     *****/
182*37da2899SCharles.Forsyth   /*****                                                               *****/
183*37da2899SCharles.Forsyth   /*****   - For one byte characters, "charcode" is simply the         *****/
184*37da2899SCharles.Forsyth   /*****     character code.                                           *****/
185*37da2899SCharles.Forsyth   /*****                                                               *****/
186*37da2899SCharles.Forsyth   /*****   - For two byte characters, "charcode" is the 2-byte         *****/
187*37da2899SCharles.Forsyth   /*****     character code in big endian format.  More exactly:       *****/
188*37da2899SCharles.Forsyth   /*****                                                               *****/
189*37da2899SCharles.Forsyth   /*****       (charcode >> 8)    is the first byte value              *****/
190*37da2899SCharles.Forsyth   /*****       (charcode & 0xFF)  is the second byte value             *****/
191*37da2899SCharles.Forsyth   /*****                                                               *****/
192*37da2899SCharles.Forsyth   /***** Note that not all values of "charcode" are valid according    *****/
193*37da2899SCharles.Forsyth   /***** to these rules, and the function moderately check the         *****/
194*37da2899SCharles.Forsyth   /***** arguments.                                                    *****/
195*37da2899SCharles.Forsyth   /*****                                                               *****/
196*37da2899SCharles.Forsyth   /*************************************************************************/
197*37da2899SCharles.Forsyth   /*************************************************************************/
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth   /*************************************************************************/
200*37da2899SCharles.Forsyth   /*                                                                       */
201*37da2899SCharles.Forsyth   /* TABLE OVERVIEW                                                        */
202*37da2899SCharles.Forsyth   /* --------------                                                        */
203*37da2899SCharles.Forsyth   /*                                                                       */
204*37da2899SCharles.Forsyth   /*   NAME        OFFSET         TYPE            DESCRIPTION              */
205*37da2899SCharles.Forsyth   /*                                                                       */
206*37da2899SCharles.Forsyth   /*   format      0              USHORT          must be 2                */
207*37da2899SCharles.Forsyth   /*   length      2              USHORT          table length in bytes    */
208*37da2899SCharles.Forsyth   /*   language    4              USHORT          Mac language code        */
209*37da2899SCharles.Forsyth   /*   keys        6              USHORT[256]     sub-header keys          */
210*37da2899SCharles.Forsyth   /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
211*37da2899SCharles.Forsyth   /*   glyph_ids   518+NSUB*8     USHORT[]        glyph id array           */
212*37da2899SCharles.Forsyth   /*                                                                       */
213*37da2899SCharles.Forsyth   /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
214*37da2899SCharles.Forsyth   /* The value of `NSUBS' is the number of sub-headers defined in the      */
215*37da2899SCharles.Forsyth   /* table and is computed by finding the maximum of the `keys' table.     */
216*37da2899SCharles.Forsyth   /*                                                                       */
217*37da2899SCharles.Forsyth   /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
218*37da2899SCharles.Forsyth   /* table, i.e., it is the corresponding sub-header index multiplied      */
219*37da2899SCharles.Forsyth   /* by 8.                                                                 */
220*37da2899SCharles.Forsyth   /*                                                                       */
221*37da2899SCharles.Forsyth   /* Each sub-header has the following format:                             */
222*37da2899SCharles.Forsyth   /*                                                                       */
223*37da2899SCharles.Forsyth   /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
224*37da2899SCharles.Forsyth   /*                                                                       */
225*37da2899SCharles.Forsyth   /*   first       0           USHORT          first valid low-byte        */
226*37da2899SCharles.Forsyth   /*   count       2           USHORT          number of valid low-bytes   */
227*37da2899SCharles.Forsyth   /*   delta       4           SHORT           see below                   */
228*37da2899SCharles.Forsyth   /*   offset      6           USHORT          see below                   */
229*37da2899SCharles.Forsyth   /*                                                                       */
230*37da2899SCharles.Forsyth   /* A sub-header defines, for each high-byte, the range of valid          */
231*37da2899SCharles.Forsyth   /* low-bytes within the charmap.  Note that the range defined by `first' */
232*37da2899SCharles.Forsyth   /* and `count' must be completely included in the interval [0..255]      */
233*37da2899SCharles.Forsyth   /* according to the specification.                                       */
234*37da2899SCharles.Forsyth   /*                                                                       */
235*37da2899SCharles.Forsyth   /* If a character code is contained within a given sub-header, then      */
236*37da2899SCharles.Forsyth   /* mapping it to a glyph index is done as follows:                       */
237*37da2899SCharles.Forsyth   /*                                                                       */
238*37da2899SCharles.Forsyth   /* * The value of `offset' is read.  This is a _byte_ distance from the  */
239*37da2899SCharles.Forsyth   /*   location of the `offset' field itself into a slice of the           */
240*37da2899SCharles.Forsyth   /*   `glyph_ids' table.  Let's call it `slice' (it's a USHORT[] too).    */
241*37da2899SCharles.Forsyth   /*                                                                       */
242*37da2899SCharles.Forsyth   /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
243*37da2899SCharles.Forsyth   /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
244*37da2899SCharles.Forsyth   /*   added to it (modulo 65536) to form a new glyph index.               */
245*37da2899SCharles.Forsyth   /*                                                                       */
246*37da2899SCharles.Forsyth   /* It is up to the validation routine to check that all offsets fall     */
247*37da2899SCharles.Forsyth   /* within the glyph ids table (and not within the `subs' table itself or */
248*37da2899SCharles.Forsyth   /* outside of the CMap).                                                 */
249*37da2899SCharles.Forsyth   /*                                                                       */
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_2
252*37da2899SCharles.Forsyth 
253*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
tt_cmap2_validate(FT_Byte * table,FT_Validator valid)254*37da2899SCharles.Forsyth   tt_cmap2_validate( FT_Byte*      table,
255*37da2899SCharles.Forsyth                      FT_Validator  valid )
256*37da2899SCharles.Forsyth   {
257*37da2899SCharles.Forsyth     FT_Byte*  p      = table + 2;           /* skip format */
258*37da2899SCharles.Forsyth     FT_UInt   length = TT_PEEK_USHORT( p );
259*37da2899SCharles.Forsyth     FT_UInt   n, max_subs;
260*37da2899SCharles.Forsyth     FT_Byte*  keys;                         /* keys table */
261*37da2899SCharles.Forsyth     FT_Byte*  subs;                         /* sub-headers */
262*37da2899SCharles.Forsyth     FT_Byte*  glyph_ids;                    /* glyph id array */
263*37da2899SCharles.Forsyth 
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth     if ( table + length > valid->limit || length < 6 + 512 )
266*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth     keys = table + 6;
269*37da2899SCharles.Forsyth 
270*37da2899SCharles.Forsyth     /* parse keys to compute sub-headers count */
271*37da2899SCharles.Forsyth     p        = keys;
272*37da2899SCharles.Forsyth     max_subs = 0;
273*37da2899SCharles.Forsyth     for ( n = 0; n < 256; n++ )
274*37da2899SCharles.Forsyth     {
275*37da2899SCharles.Forsyth       FT_UInt  idx = TT_NEXT_USHORT( p );
276*37da2899SCharles.Forsyth 
277*37da2899SCharles.Forsyth 
278*37da2899SCharles.Forsyth       /* value must be multiple of 8 */
279*37da2899SCharles.Forsyth       if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
280*37da2899SCharles.Forsyth         FT_INVALID_DATA;
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth       idx >>= 3;
283*37da2899SCharles.Forsyth 
284*37da2899SCharles.Forsyth       if ( idx > max_subs )
285*37da2899SCharles.Forsyth         max_subs = idx;
286*37da2899SCharles.Forsyth     }
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth     FT_ASSERT( p == table + 518 );
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth     subs      = p;
291*37da2899SCharles.Forsyth     glyph_ids = subs + (max_subs + 1) * 8;
292*37da2899SCharles.Forsyth     if ( glyph_ids > valid->limit )
293*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
294*37da2899SCharles.Forsyth 
295*37da2899SCharles.Forsyth     /* parse sub-headers */
296*37da2899SCharles.Forsyth     for ( n = 0; n <= max_subs; n++ )
297*37da2899SCharles.Forsyth     {
298*37da2899SCharles.Forsyth       FT_UInt   first_code, code_count, offset;
299*37da2899SCharles.Forsyth       FT_Int    delta;
300*37da2899SCharles.Forsyth       FT_Byte*  ids;
301*37da2899SCharles.Forsyth 
302*37da2899SCharles.Forsyth 
303*37da2899SCharles.Forsyth       first_code = TT_NEXT_USHORT( p );
304*37da2899SCharles.Forsyth       code_count = TT_NEXT_USHORT( p );
305*37da2899SCharles.Forsyth       delta      = TT_NEXT_SHORT( p );
306*37da2899SCharles.Forsyth       offset     = TT_NEXT_USHORT( p );
307*37da2899SCharles.Forsyth 
308*37da2899SCharles.Forsyth       /* check range within 0..255 */
309*37da2899SCharles.Forsyth       if ( valid->level >= FT_VALIDATE_PARANOID )
310*37da2899SCharles.Forsyth       {
311*37da2899SCharles.Forsyth         if ( first_code >= 256 || first_code + code_count > 256 )
312*37da2899SCharles.Forsyth           FT_INVALID_DATA;
313*37da2899SCharles.Forsyth       }
314*37da2899SCharles.Forsyth 
315*37da2899SCharles.Forsyth       /* check offset */
316*37da2899SCharles.Forsyth       if ( offset != 0 )
317*37da2899SCharles.Forsyth       {
318*37da2899SCharles.Forsyth         ids = p - 2 + offset;
319*37da2899SCharles.Forsyth         if ( ids < glyph_ids || ids + code_count*2 > table + length )
320*37da2899SCharles.Forsyth           FT_INVALID_OFFSET;
321*37da2899SCharles.Forsyth 
322*37da2899SCharles.Forsyth         /* check glyph ids */
323*37da2899SCharles.Forsyth         if ( valid->level >= FT_VALIDATE_TIGHT )
324*37da2899SCharles.Forsyth         {
325*37da2899SCharles.Forsyth           FT_Byte*  limit = p + code_count * 2;
326*37da2899SCharles.Forsyth           FT_UInt   idx;
327*37da2899SCharles.Forsyth 
328*37da2899SCharles.Forsyth 
329*37da2899SCharles.Forsyth           for ( ; p < limit; )
330*37da2899SCharles.Forsyth           {
331*37da2899SCharles.Forsyth             idx = TT_NEXT_USHORT( p );
332*37da2899SCharles.Forsyth             if ( idx != 0 )
333*37da2899SCharles.Forsyth             {
334*37da2899SCharles.Forsyth               idx = ( idx + delta ) & 0xFFFFU;
335*37da2899SCharles.Forsyth               if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
336*37da2899SCharles.Forsyth                 FT_INVALID_GLYPH_ID;
337*37da2899SCharles.Forsyth             }
338*37da2899SCharles.Forsyth           }
339*37da2899SCharles.Forsyth         }
340*37da2899SCharles.Forsyth       }
341*37da2899SCharles.Forsyth     }
342*37da2899SCharles.Forsyth   }
343*37da2899SCharles.Forsyth 
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth   /* return sub header corresponding to a given character code */
346*37da2899SCharles.Forsyth   /* NULL on invalid charcode                                  */
347*37da2899SCharles.Forsyth   static FT_Byte*
tt_cmap2_get_subheader(FT_Byte * table,FT_UInt32 char_code)348*37da2899SCharles.Forsyth   tt_cmap2_get_subheader( FT_Byte*   table,
349*37da2899SCharles.Forsyth                           FT_UInt32  char_code )
350*37da2899SCharles.Forsyth   {
351*37da2899SCharles.Forsyth     FT_Byte*  result = NULL;
352*37da2899SCharles.Forsyth 
353*37da2899SCharles.Forsyth 
354*37da2899SCharles.Forsyth     if ( char_code < 0x10000UL )
355*37da2899SCharles.Forsyth     {
356*37da2899SCharles.Forsyth       FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
357*37da2899SCharles.Forsyth       FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
358*37da2899SCharles.Forsyth       FT_Byte*  p       = table + 6;    /* keys table */
359*37da2899SCharles.Forsyth       FT_Byte*  subs    = table + 518;  /* subheaders table */
360*37da2899SCharles.Forsyth       FT_Byte*  sub;
361*37da2899SCharles.Forsyth 
362*37da2899SCharles.Forsyth 
363*37da2899SCharles.Forsyth       if ( char_hi == 0 )
364*37da2899SCharles.Forsyth       {
365*37da2899SCharles.Forsyth         /* an 8-bit character code -- we use subHeader 0 in this case */
366*37da2899SCharles.Forsyth         /* to test whether the character code is in the charmap       */
367*37da2899SCharles.Forsyth         /*                                                            */
368*37da2899SCharles.Forsyth         sub = subs;  /* jump to first sub-header */
369*37da2899SCharles.Forsyth 
370*37da2899SCharles.Forsyth         /* check that the sub-header for this byte is 0, which */
371*37da2899SCharles.Forsyth         /* indicates that it's really a valid one-byte value   */
372*37da2899SCharles.Forsyth         /* Otherwise, return 0                                 */
373*37da2899SCharles.Forsyth         /*                                                     */
374*37da2899SCharles.Forsyth         p += char_lo * 2;
375*37da2899SCharles.Forsyth         if ( TT_PEEK_USHORT( p ) != 0 )
376*37da2899SCharles.Forsyth           goto Exit;
377*37da2899SCharles.Forsyth       }
378*37da2899SCharles.Forsyth       else
379*37da2899SCharles.Forsyth       {
380*37da2899SCharles.Forsyth         /* a 16-bit character code */
381*37da2899SCharles.Forsyth         p  += char_hi * 2;                          /* jump to key entry  */
382*37da2899SCharles.Forsyth         sub = subs + ( TT_PEEK_USHORT( p ) & -8 );  /* jump to sub-header */
383*37da2899SCharles.Forsyth 
384*37da2899SCharles.Forsyth         /* check that the hi byte isn't a valid one-byte value */
385*37da2899SCharles.Forsyth         if ( sub == subs )
386*37da2899SCharles.Forsyth           goto Exit;
387*37da2899SCharles.Forsyth       }
388*37da2899SCharles.Forsyth       result = sub;
389*37da2899SCharles.Forsyth     }
390*37da2899SCharles.Forsyth   Exit:
391*37da2899SCharles.Forsyth     return result;
392*37da2899SCharles.Forsyth   }
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth 
395*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap2_char_index(TT_CMap cmap,FT_UInt32 char_code)396*37da2899SCharles.Forsyth   tt_cmap2_char_index( TT_CMap    cmap,
397*37da2899SCharles.Forsyth                        FT_UInt32  char_code )
398*37da2899SCharles.Forsyth   {
399*37da2899SCharles.Forsyth     FT_Byte*  table   = cmap->data;
400*37da2899SCharles.Forsyth     FT_UInt   result  = 0;
401*37da2899SCharles.Forsyth     FT_Byte*  subheader;
402*37da2899SCharles.Forsyth 
403*37da2899SCharles.Forsyth 
404*37da2899SCharles.Forsyth     subheader = tt_cmap2_get_subheader( table, char_code );
405*37da2899SCharles.Forsyth     if ( subheader )
406*37da2899SCharles.Forsyth     {
407*37da2899SCharles.Forsyth       FT_Byte*  p   = subheader;
408*37da2899SCharles.Forsyth       FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
409*37da2899SCharles.Forsyth       FT_UInt   start, count;
410*37da2899SCharles.Forsyth       FT_Int    delta;
411*37da2899SCharles.Forsyth       FT_UInt   offset;
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth 
414*37da2899SCharles.Forsyth       start  = TT_NEXT_USHORT( p );
415*37da2899SCharles.Forsyth       count  = TT_NEXT_USHORT( p );
416*37da2899SCharles.Forsyth       delta  = TT_NEXT_SHORT ( p );
417*37da2899SCharles.Forsyth       offset = TT_PEEK_USHORT( p );
418*37da2899SCharles.Forsyth 
419*37da2899SCharles.Forsyth       idx -= start;
420*37da2899SCharles.Forsyth       if ( idx < count && offset != 0 )
421*37da2899SCharles.Forsyth       {
422*37da2899SCharles.Forsyth         p  += offset + 2 * idx;
423*37da2899SCharles.Forsyth         idx = TT_PEEK_USHORT( p );
424*37da2899SCharles.Forsyth 
425*37da2899SCharles.Forsyth         if ( idx != 0 )
426*37da2899SCharles.Forsyth           result = (FT_UInt)( idx + delta ) & 0xFFFFU;
427*37da2899SCharles.Forsyth       }
428*37da2899SCharles.Forsyth     }
429*37da2899SCharles.Forsyth     return result;
430*37da2899SCharles.Forsyth   }
431*37da2899SCharles.Forsyth 
432*37da2899SCharles.Forsyth 
433*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap2_char_next(TT_CMap cmap,FT_UInt32 * pcharcode)434*37da2899SCharles.Forsyth   tt_cmap2_char_next( TT_CMap     cmap,
435*37da2899SCharles.Forsyth                       FT_UInt32  *pcharcode )
436*37da2899SCharles.Forsyth   {
437*37da2899SCharles.Forsyth     FT_Byte*   table    = cmap->data;
438*37da2899SCharles.Forsyth     FT_UInt    gindex   = 0;
439*37da2899SCharles.Forsyth     FT_UInt32  result   = 0;
440*37da2899SCharles.Forsyth     FT_UInt32  charcode = *pcharcode + 1;
441*37da2899SCharles.Forsyth     FT_Byte*   subheader;
442*37da2899SCharles.Forsyth 
443*37da2899SCharles.Forsyth 
444*37da2899SCharles.Forsyth     while ( charcode < 0x10000UL )
445*37da2899SCharles.Forsyth     {
446*37da2899SCharles.Forsyth       subheader = tt_cmap2_get_subheader( table, charcode );
447*37da2899SCharles.Forsyth       if ( subheader )
448*37da2899SCharles.Forsyth       {
449*37da2899SCharles.Forsyth         FT_Byte*  p       = subheader;
450*37da2899SCharles.Forsyth         FT_UInt   start   = TT_NEXT_USHORT( p );
451*37da2899SCharles.Forsyth         FT_UInt   count   = TT_NEXT_USHORT( p );
452*37da2899SCharles.Forsyth         FT_Int    delta   = TT_NEXT_SHORT ( p );
453*37da2899SCharles.Forsyth         FT_UInt   offset  = TT_PEEK_USHORT( p );
454*37da2899SCharles.Forsyth         FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
455*37da2899SCharles.Forsyth         FT_UInt   pos, idx;
456*37da2899SCharles.Forsyth 
457*37da2899SCharles.Forsyth 
458*37da2899SCharles.Forsyth         if ( offset == 0 )
459*37da2899SCharles.Forsyth           goto Next_SubHeader;
460*37da2899SCharles.Forsyth 
461*37da2899SCharles.Forsyth         if ( char_lo < start )
462*37da2899SCharles.Forsyth         {
463*37da2899SCharles.Forsyth           char_lo = start;
464*37da2899SCharles.Forsyth           pos     = 0;
465*37da2899SCharles.Forsyth         }
466*37da2899SCharles.Forsyth         else
467*37da2899SCharles.Forsyth           pos = (FT_UInt)( char_lo - start );
468*37da2899SCharles.Forsyth 
469*37da2899SCharles.Forsyth         p       += offset + pos * 2;
470*37da2899SCharles.Forsyth         charcode = ( charcode & -256 ) + char_lo;
471*37da2899SCharles.Forsyth 
472*37da2899SCharles.Forsyth         for ( ; pos < count; pos++, charcode++ )
473*37da2899SCharles.Forsyth         {
474*37da2899SCharles.Forsyth           idx = TT_NEXT_USHORT( p );
475*37da2899SCharles.Forsyth 
476*37da2899SCharles.Forsyth           if ( idx != 0 )
477*37da2899SCharles.Forsyth           {
478*37da2899SCharles.Forsyth             gindex = ( idx + delta ) & 0xFFFFU;
479*37da2899SCharles.Forsyth             if ( gindex != 0 )
480*37da2899SCharles.Forsyth             {
481*37da2899SCharles.Forsyth               result = charcode;
482*37da2899SCharles.Forsyth               goto Exit;
483*37da2899SCharles.Forsyth             }
484*37da2899SCharles.Forsyth           }
485*37da2899SCharles.Forsyth         }
486*37da2899SCharles.Forsyth       }
487*37da2899SCharles.Forsyth 
488*37da2899SCharles.Forsyth       /* jump to next sub-header, i.e. higher byte value */
489*37da2899SCharles.Forsyth     Next_SubHeader:
490*37da2899SCharles.Forsyth       charcode = ( charcode & -256 ) + 256;
491*37da2899SCharles.Forsyth     }
492*37da2899SCharles.Forsyth 
493*37da2899SCharles.Forsyth   Exit:
494*37da2899SCharles.Forsyth     *pcharcode = result;
495*37da2899SCharles.Forsyth 
496*37da2899SCharles.Forsyth     return gindex;
497*37da2899SCharles.Forsyth   }
498*37da2899SCharles.Forsyth 
499*37da2899SCharles.Forsyth 
500*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
501*37da2899SCharles.Forsyth   const TT_CMap_ClassRec  tt_cmap2_class_rec =
502*37da2899SCharles.Forsyth   {
503*37da2899SCharles.Forsyth     {
504*37da2899SCharles.Forsyth       sizeof( TT_CMapRec ),
505*37da2899SCharles.Forsyth 
506*37da2899SCharles.Forsyth       (FT_CMap_InitFunc)     tt_cmap_init,
507*37da2899SCharles.Forsyth       (FT_CMap_DoneFunc)     NULL,
508*37da2899SCharles.Forsyth       (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
509*37da2899SCharles.Forsyth       (FT_CMap_CharNextFunc) tt_cmap2_char_next
510*37da2899SCharles.Forsyth     },
511*37da2899SCharles.Forsyth     2,
512*37da2899SCharles.Forsyth     (TT_CMap_ValidateFunc)   tt_cmap2_validate
513*37da2899SCharles.Forsyth   };
514*37da2899SCharles.Forsyth 
515*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_2 */
516*37da2899SCharles.Forsyth 
517*37da2899SCharles.Forsyth 
518*37da2899SCharles.Forsyth   /*************************************************************************/
519*37da2899SCharles.Forsyth   /*************************************************************************/
520*37da2899SCharles.Forsyth   /*****                                                               *****/
521*37da2899SCharles.Forsyth   /*****                           FORMAT 4                            *****/
522*37da2899SCharles.Forsyth   /*****                                                               *****/
523*37da2899SCharles.Forsyth   /*************************************************************************/
524*37da2899SCharles.Forsyth   /*************************************************************************/
525*37da2899SCharles.Forsyth 
526*37da2899SCharles.Forsyth   /*************************************************************************/
527*37da2899SCharles.Forsyth   /*                                                                       */
528*37da2899SCharles.Forsyth   /* TABLE OVERVIEW                                                        */
529*37da2899SCharles.Forsyth   /* --------------                                                        */
530*37da2899SCharles.Forsyth   /*                                                                       */
531*37da2899SCharles.Forsyth   /*   NAME          OFFSET         TYPE              DESCRIPTION          */
532*37da2899SCharles.Forsyth   /*                                                                       */
533*37da2899SCharles.Forsyth   /*   format        0              USHORT            must be 4            */
534*37da2899SCharles.Forsyth   /*   length        2              USHORT            table length         */
535*37da2899SCharles.Forsyth   /*                                                  in bytes             */
536*37da2899SCharles.Forsyth   /*   language      4              USHORT            Mac language code    */
537*37da2899SCharles.Forsyth   /*                                                                       */
538*37da2899SCharles.Forsyth   /*   segCountX2    6              USHORT            2*NUM_SEGS           */
539*37da2899SCharles.Forsyth   /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
540*37da2899SCharles.Forsyth   /*   entrySelector 10             USHORT            LOG_SEGS             */
541*37da2899SCharles.Forsyth   /*   rangeShift    12             USHORT            segCountX2 -         */
542*37da2899SCharles.Forsyth   /*                                                    searchRange        */
543*37da2899SCharles.Forsyth   /*                                                                       */
544*37da2899SCharles.Forsyth   /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
545*37da2899SCharles.Forsyth   /*                                                  each segment; last   */
546*37da2899SCharles.Forsyth   /*                                                  is 0xFFFF            */
547*37da2899SCharles.Forsyth   /*                                                                       */
548*37da2899SCharles.Forsyth   /*   pad           14+NUM_SEGS*2  USHORT            padding              */
549*37da2899SCharles.Forsyth   /*                                                                       */
550*37da2899SCharles.Forsyth   /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
551*37da2899SCharles.Forsyth   /*                                                  each segment         */
552*37da2899SCharles.Forsyth   /*                                                                       */
553*37da2899SCharles.Forsyth   /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
554*37da2899SCharles.Forsyth   /*                                                  segment              */
555*37da2899SCharles.Forsyth   /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
556*37da2899SCharles.Forsyth   /*                                                  each segment; can be */
557*37da2899SCharles.Forsyth   /*                                                  zero                 */
558*37da2899SCharles.Forsyth   /*                                                                       */
559*37da2899SCharles.Forsyth   /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph id    */
560*37da2899SCharles.Forsyth   /*                                                  ranges               */
561*37da2899SCharles.Forsyth   /*                                                                       */
562*37da2899SCharles.Forsyth   /* Character codes are modelled by a series of ordered (increasing)      */
563*37da2899SCharles.Forsyth   /* intervals called segments.  Each segment has start and end codes,     */
564*37da2899SCharles.Forsyth   /* provided by the `startCount' and `endCount' arrays.  Segments must    */
565*37da2899SCharles.Forsyth   /* not be overlapping and the last segment should always contain the     */
566*37da2899SCharles.Forsyth   /* `0xFFFF' endCount.                                                    */
567*37da2899SCharles.Forsyth   /*                                                                       */
568*37da2899SCharles.Forsyth   /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
569*37da2899SCharles.Forsyth   /* ignored (they are traces of over-engineering in the TrueType          */
570*37da2899SCharles.Forsyth   /* specification).                                                       */
571*37da2899SCharles.Forsyth   /*                                                                       */
572*37da2899SCharles.Forsyth   /* Each segment also has a signed `delta', as well as an optional offset */
573*37da2899SCharles.Forsyth   /* within the `glyphIds' table.                                          */
574*37da2899SCharles.Forsyth   /*                                                                       */
575*37da2899SCharles.Forsyth   /* If a segment's idOffset is 0, the glyph index corresponding to any    */
576*37da2899SCharles.Forsyth   /* charcode within the segment is obtained by adding the value of        */
577*37da2899SCharles.Forsyth   /* `idDelta' directly to the charcode, modulo 65536.                     */
578*37da2899SCharles.Forsyth   /*                                                                       */
579*37da2899SCharles.Forsyth   /* Otherwise, a glyph index is taken from the glyph ids sub-array for    */
580*37da2899SCharles.Forsyth   /* the segment, and the value of `idDelta' is added to it.               */
581*37da2899SCharles.Forsyth   /*                                                                       */
582*37da2899SCharles.Forsyth   /*                                                                       */
583*37da2899SCharles.Forsyth   /* Finally, note that certain fonts contain invalid charmaps that        */
584*37da2899SCharles.Forsyth   /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the  */
585*37da2899SCharles.Forsyth   /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */
586*37da2899SCharles.Forsyth   /* we need special code to deal with them correctly...                   */
587*37da2899SCharles.Forsyth   /*                                                                       */
588*37da2899SCharles.Forsyth 
589*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_4
590*37da2899SCharles.Forsyth 
591*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
tt_cmap4_validate(FT_Byte * table,FT_Validator valid)592*37da2899SCharles.Forsyth   tt_cmap4_validate( FT_Byte*      table,
593*37da2899SCharles.Forsyth                      FT_Validator  valid )
594*37da2899SCharles.Forsyth   {
595*37da2899SCharles.Forsyth     FT_Byte*  p      = table + 2;               /* skip format */
596*37da2899SCharles.Forsyth     FT_UInt   length = TT_NEXT_USHORT( p );
597*37da2899SCharles.Forsyth     FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
598*37da2899SCharles.Forsyth     FT_UInt   num_segs;
599*37da2899SCharles.Forsyth 
600*37da2899SCharles.Forsyth 
601*37da2899SCharles.Forsyth     /* in certain fonts, the `length' field is invalid and goes */
602*37da2899SCharles.Forsyth     /* out of bound.  We try to correct this here...            */
603*37da2899SCharles.Forsyth     if ( length < 16 )
604*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
605*37da2899SCharles.Forsyth 
606*37da2899SCharles.Forsyth     if ( table + length > valid->limit )
607*37da2899SCharles.Forsyth     {
608*37da2899SCharles.Forsyth       if ( valid->level >= FT_VALIDATE_TIGHT )
609*37da2899SCharles.Forsyth         FT_INVALID_TOO_SHORT;
610*37da2899SCharles.Forsyth 
611*37da2899SCharles.Forsyth       length = (FT_UInt)( valid->limit - table );
612*37da2899SCharles.Forsyth     }
613*37da2899SCharles.Forsyth 
614*37da2899SCharles.Forsyth     p        = table + 6;
615*37da2899SCharles.Forsyth     num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
616*37da2899SCharles.Forsyth 
617*37da2899SCharles.Forsyth     if ( valid->level >= FT_VALIDATE_PARANOID )
618*37da2899SCharles.Forsyth     {
619*37da2899SCharles.Forsyth       /* check that we have an even value here */
620*37da2899SCharles.Forsyth       if ( num_segs & 1 )
621*37da2899SCharles.Forsyth         FT_INVALID_DATA;
622*37da2899SCharles.Forsyth     }
623*37da2899SCharles.Forsyth 
624*37da2899SCharles.Forsyth     num_segs /= 2;
625*37da2899SCharles.Forsyth 
626*37da2899SCharles.Forsyth     /* check the search parameters - even though we never use them */
627*37da2899SCharles.Forsyth     /*                                                             */
628*37da2899SCharles.Forsyth     if ( valid->level >= FT_VALIDATE_PARANOID )
629*37da2899SCharles.Forsyth     {
630*37da2899SCharles.Forsyth       /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
631*37da2899SCharles.Forsyth       FT_UInt  search_range   = TT_NEXT_USHORT( p );
632*37da2899SCharles.Forsyth       FT_UInt  entry_selector = TT_NEXT_USHORT( p );
633*37da2899SCharles.Forsyth       FT_UInt  range_shift    = TT_NEXT_USHORT( p );
634*37da2899SCharles.Forsyth 
635*37da2899SCharles.Forsyth 
636*37da2899SCharles.Forsyth       if ( ( search_range | range_shift ) & 1 )  /* must be even values */
637*37da2899SCharles.Forsyth         FT_INVALID_DATA;
638*37da2899SCharles.Forsyth 
639*37da2899SCharles.Forsyth       search_range /= 2;
640*37da2899SCharles.Forsyth       range_shift  /= 2;
641*37da2899SCharles.Forsyth 
642*37da2899SCharles.Forsyth       /* `search range' is the greatest power of 2 that is <= num_segs */
643*37da2899SCharles.Forsyth 
644*37da2899SCharles.Forsyth       if ( search_range                > num_segs                 ||
645*37da2899SCharles.Forsyth            search_range * 2            < num_segs                 ||
646*37da2899SCharles.Forsyth            search_range + range_shift != num_segs                 ||
647*37da2899SCharles.Forsyth            search_range               != ( 1U << entry_selector ) )
648*37da2899SCharles.Forsyth         FT_INVALID_DATA;
649*37da2899SCharles.Forsyth     }
650*37da2899SCharles.Forsyth 
651*37da2899SCharles.Forsyth     ends      = table   + 14;
652*37da2899SCharles.Forsyth     starts    = table   + 16 + num_segs * 2;
653*37da2899SCharles.Forsyth     deltas    = starts  + num_segs * 2;
654*37da2899SCharles.Forsyth     offsets   = deltas  + num_segs * 2;
655*37da2899SCharles.Forsyth     glyph_ids = offsets + num_segs * 2;
656*37da2899SCharles.Forsyth 
657*37da2899SCharles.Forsyth     if ( glyph_ids > table + length )
658*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
659*37da2899SCharles.Forsyth 
660*37da2899SCharles.Forsyth     /* check last segment, its end count must be FFFF */
661*37da2899SCharles.Forsyth     if ( valid->level >= FT_VALIDATE_PARANOID )
662*37da2899SCharles.Forsyth     {
663*37da2899SCharles.Forsyth       p = ends + ( num_segs - 1 ) * 2;
664*37da2899SCharles.Forsyth       if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
665*37da2899SCharles.Forsyth         FT_INVALID_DATA;
666*37da2899SCharles.Forsyth     }
667*37da2899SCharles.Forsyth 
668*37da2899SCharles.Forsyth     /* check that segments are sorted in increasing order and do not */
669*37da2899SCharles.Forsyth     /* overlap; check also the offsets                               */
670*37da2899SCharles.Forsyth     {
671*37da2899SCharles.Forsyth       FT_UInt  start, end, last = 0, offset, n;
672*37da2899SCharles.Forsyth       FT_Int   delta;
673*37da2899SCharles.Forsyth 
674*37da2899SCharles.Forsyth 
675*37da2899SCharles.Forsyth       for ( n = 0; n < num_segs; n++ )
676*37da2899SCharles.Forsyth       {
677*37da2899SCharles.Forsyth         p = starts + n * 2;
678*37da2899SCharles.Forsyth         start = TT_PEEK_USHORT( p );
679*37da2899SCharles.Forsyth         p = ends + n * 2;
680*37da2899SCharles.Forsyth         end = TT_PEEK_USHORT( p );
681*37da2899SCharles.Forsyth         p = deltas + n * 2;
682*37da2899SCharles.Forsyth         delta = TT_PEEK_SHORT( p );
683*37da2899SCharles.Forsyth         p = offsets + n * 2;
684*37da2899SCharles.Forsyth         offset = TT_PEEK_USHORT( p );
685*37da2899SCharles.Forsyth 
686*37da2899SCharles.Forsyth         if ( start > end )
687*37da2899SCharles.Forsyth           FT_INVALID_DATA;
688*37da2899SCharles.Forsyth 
689*37da2899SCharles.Forsyth         /* this test should be performed at default validation level;  */
690*37da2899SCharles.Forsyth         /* unfortunately, some popular Asian fonts present overlapping */
691*37da2899SCharles.Forsyth         /* ranges in their charmaps                                    */
692*37da2899SCharles.Forsyth         /*                                                             */
693*37da2899SCharles.Forsyth         if ( valid->level >= FT_VALIDATE_TIGHT )
694*37da2899SCharles.Forsyth         {
695*37da2899SCharles.Forsyth           if ( n > 0 && start <= last )
696*37da2899SCharles.Forsyth             FT_INVALID_DATA;
697*37da2899SCharles.Forsyth         }
698*37da2899SCharles.Forsyth 
699*37da2899SCharles.Forsyth         if ( offset && offset != 0xFFFFU )
700*37da2899SCharles.Forsyth         {
701*37da2899SCharles.Forsyth           p += offset;  /* start of glyph id array */
702*37da2899SCharles.Forsyth 
703*37da2899SCharles.Forsyth           /* check that we point within the glyph ids table only */
704*37da2899SCharles.Forsyth           if ( p < glyph_ids                                ||
705*37da2899SCharles.Forsyth                p + ( end - start + 1 ) * 2 > table + length )
706*37da2899SCharles.Forsyth             FT_INVALID_DATA;
707*37da2899SCharles.Forsyth 
708*37da2899SCharles.Forsyth           /* check glyph indices within the segment range */
709*37da2899SCharles.Forsyth           if ( valid->level >= FT_VALIDATE_TIGHT )
710*37da2899SCharles.Forsyth           {
711*37da2899SCharles.Forsyth             FT_UInt  i, idx;
712*37da2899SCharles.Forsyth 
713*37da2899SCharles.Forsyth 
714*37da2899SCharles.Forsyth             for ( i = start; i < end; i++ )
715*37da2899SCharles.Forsyth             {
716*37da2899SCharles.Forsyth               idx = FT_NEXT_USHORT( p );
717*37da2899SCharles.Forsyth               if ( idx != 0 )
718*37da2899SCharles.Forsyth               {
719*37da2899SCharles.Forsyth                 idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
720*37da2899SCharles.Forsyth 
721*37da2899SCharles.Forsyth                 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
722*37da2899SCharles.Forsyth                   FT_INVALID_GLYPH_ID;
723*37da2899SCharles.Forsyth               }
724*37da2899SCharles.Forsyth             }
725*37da2899SCharles.Forsyth           }
726*37da2899SCharles.Forsyth         }
727*37da2899SCharles.Forsyth         else if ( offset == 0xFFFFU )
728*37da2899SCharles.Forsyth         {
729*37da2899SCharles.Forsyth           /* Some fonts (erroneously?) use a range offset of 0xFFFF */
730*37da2899SCharles.Forsyth           /* to mean missing glyph in cmap table                    */
731*37da2899SCharles.Forsyth           /*                                                        */
732*37da2899SCharles.Forsyth           if ( valid->level >= FT_VALIDATE_PARANOID                     ||
733*37da2899SCharles.Forsyth                n != num_segs - 1                                        ||
734*37da2899SCharles.Forsyth                !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) )
735*37da2899SCharles.Forsyth             FT_INVALID_DATA;
736*37da2899SCharles.Forsyth         }
737*37da2899SCharles.Forsyth 
738*37da2899SCharles.Forsyth         last = end;
739*37da2899SCharles.Forsyth       }
740*37da2899SCharles.Forsyth     }
741*37da2899SCharles.Forsyth   }
742*37da2899SCharles.Forsyth 
743*37da2899SCharles.Forsyth 
744*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap4_char_index(TT_CMap cmap,FT_UInt32 char_code)745*37da2899SCharles.Forsyth   tt_cmap4_char_index( TT_CMap    cmap,
746*37da2899SCharles.Forsyth                        FT_UInt32  char_code )
747*37da2899SCharles.Forsyth   {
748*37da2899SCharles.Forsyth     FT_Byte*  table  = cmap->data;
749*37da2899SCharles.Forsyth     FT_UInt   result = 0;
750*37da2899SCharles.Forsyth 
751*37da2899SCharles.Forsyth 
752*37da2899SCharles.Forsyth     if ( char_code < 0x10000UL )
753*37da2899SCharles.Forsyth     {
754*37da2899SCharles.Forsyth       FT_UInt   idx, num_segs2;
755*37da2899SCharles.Forsyth       FT_Int    delta;
756*37da2899SCharles.Forsyth       FT_UInt   code = (FT_UInt)char_code;
757*37da2899SCharles.Forsyth       FT_Byte*  p;
758*37da2899SCharles.Forsyth 
759*37da2899SCharles.Forsyth 
760*37da2899SCharles.Forsyth       p         = table + 6;
761*37da2899SCharles.Forsyth       num_segs2 = TT_PEEK_USHORT( p ) & -2;  /* be paranoid! */
762*37da2899SCharles.Forsyth 
763*37da2899SCharles.Forsyth #if 1
764*37da2899SCharles.Forsyth       /* Some fonts have more than 170 segments in their charmaps! */
765*37da2899SCharles.Forsyth       /* We changed this function to use a more efficient binary   */
766*37da2899SCharles.Forsyth       /* search for improving performance                          */
767*37da2899SCharles.Forsyth       {
768*37da2899SCharles.Forsyth         FT_UInt  min = 0;
769*37da2899SCharles.Forsyth         FT_UInt  max = num_segs2 >> 1;
770*37da2899SCharles.Forsyth         FT_UInt  mid, start, end, offset;
771*37da2899SCharles.Forsyth 
772*37da2899SCharles.Forsyth 
773*37da2899SCharles.Forsyth         while ( min < max )
774*37da2899SCharles.Forsyth         {
775*37da2899SCharles.Forsyth           mid   = ( min + max ) >> 1;
776*37da2899SCharles.Forsyth           p     = table + 14 + mid * 2;
777*37da2899SCharles.Forsyth           end   = TT_NEXT_USHORT( p );
778*37da2899SCharles.Forsyth           p    += num_segs2;
779*37da2899SCharles.Forsyth           start = TT_PEEK_USHORT( p);
780*37da2899SCharles.Forsyth 
781*37da2899SCharles.Forsyth           if ( code < start )
782*37da2899SCharles.Forsyth             max = mid;
783*37da2899SCharles.Forsyth 
784*37da2899SCharles.Forsyth           else if ( code > end )
785*37da2899SCharles.Forsyth             min = mid + 1;
786*37da2899SCharles.Forsyth 
787*37da2899SCharles.Forsyth           else
788*37da2899SCharles.Forsyth           {
789*37da2899SCharles.Forsyth             /* we found the segment */
790*37da2899SCharles.Forsyth             idx = code;
791*37da2899SCharles.Forsyth 
792*37da2899SCharles.Forsyth             p += num_segs2;
793*37da2899SCharles.Forsyth             delta = TT_PEEK_SHORT( p );
794*37da2899SCharles.Forsyth 
795*37da2899SCharles.Forsyth             p += num_segs2;
796*37da2899SCharles.Forsyth             offset = TT_PEEK_USHORT( p );
797*37da2899SCharles.Forsyth 
798*37da2899SCharles.Forsyth             if ( offset == 0xFFFFU )
799*37da2899SCharles.Forsyth               goto Exit;
800*37da2899SCharles.Forsyth 
801*37da2899SCharles.Forsyth             if ( offset != 0 )
802*37da2899SCharles.Forsyth             {
803*37da2899SCharles.Forsyth               p  += offset + 2 * ( idx - start );
804*37da2899SCharles.Forsyth               idx = TT_PEEK_USHORT( p );
805*37da2899SCharles.Forsyth             }
806*37da2899SCharles.Forsyth 
807*37da2899SCharles.Forsyth             if ( idx != 0 )
808*37da2899SCharles.Forsyth               result = (FT_UInt)( idx + delta ) & 0xFFFFU;
809*37da2899SCharles.Forsyth 
810*37da2899SCharles.Forsyth             goto Exit;
811*37da2899SCharles.Forsyth           }
812*37da2899SCharles.Forsyth         }
813*37da2899SCharles.Forsyth       }
814*37da2899SCharles.Forsyth 
815*37da2899SCharles.Forsyth #else /* 0 - old code */
816*37da2899SCharles.Forsyth 
817*37da2899SCharles.Forsyth       {
818*37da2899SCharles.Forsyth         FT_UInt   n;
819*37da2899SCharles.Forsyth         FT_Byte*  q;
820*37da2899SCharles.Forsyth 
821*37da2899SCharles.Forsyth 
822*37da2899SCharles.Forsyth         p = table + 14;               /* ends table   */
823*37da2899SCharles.Forsyth         q = table + 16 + num_segs2;   /* starts table */
824*37da2899SCharles.Forsyth 
825*37da2899SCharles.Forsyth 
826*37da2899SCharles.Forsyth         for ( n = 0; n < num_segs2; n += 2 )
827*37da2899SCharles.Forsyth         {
828*37da2899SCharles.Forsyth           FT_UInt  end   = TT_NEXT_USHORT( p );
829*37da2899SCharles.Forsyth           FT_UInt  start = TT_NEXT_USHORT( q );
830*37da2899SCharles.Forsyth           FT_UInt  offset;
831*37da2899SCharles.Forsyth 
832*37da2899SCharles.Forsyth 
833*37da2899SCharles.Forsyth           if ( code < start )
834*37da2899SCharles.Forsyth             break;
835*37da2899SCharles.Forsyth 
836*37da2899SCharles.Forsyth           if ( code <= end )
837*37da2899SCharles.Forsyth           {
838*37da2899SCharles.Forsyth             idx = code;
839*37da2899SCharles.Forsyth 
840*37da2899SCharles.Forsyth             p = q + num_segs2 - 2;
841*37da2899SCharles.Forsyth             delta = TT_PEEK_SHORT( p );
842*37da2899SCharles.Forsyth             p += num_segs2;
843*37da2899SCharles.Forsyth             offset = TT_PEEK_USHORT( p );
844*37da2899SCharles.Forsyth 
845*37da2899SCharles.Forsyth             if ( offset == 0xFFFFU )
846*37da2899SCharles.Forsyth               goto Exit;
847*37da2899SCharles.Forsyth 
848*37da2899SCharles.Forsyth             if ( offset != 0 )
849*37da2899SCharles.Forsyth             {
850*37da2899SCharles.Forsyth               p  += offset + 2 * ( idx - start );
851*37da2899SCharles.Forsyth               idx = TT_PEEK_USHORT( p );
852*37da2899SCharles.Forsyth             }
853*37da2899SCharles.Forsyth 
854*37da2899SCharles.Forsyth             if ( idx != 0 )
855*37da2899SCharles.Forsyth               result = (FT_UInt)( idx + delta ) & 0xFFFFU;
856*37da2899SCharles.Forsyth           }
857*37da2899SCharles.Forsyth         }
858*37da2899SCharles.Forsyth       }
859*37da2899SCharles.Forsyth 
860*37da2899SCharles.Forsyth #endif /* 0 */
861*37da2899SCharles.Forsyth 
862*37da2899SCharles.Forsyth     }
863*37da2899SCharles.Forsyth 
864*37da2899SCharles.Forsyth   Exit:
865*37da2899SCharles.Forsyth     return result;
866*37da2899SCharles.Forsyth   }
867*37da2899SCharles.Forsyth 
868*37da2899SCharles.Forsyth 
869*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap4_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)870*37da2899SCharles.Forsyth   tt_cmap4_char_next( TT_CMap     cmap,
871*37da2899SCharles.Forsyth                       FT_UInt32  *pchar_code )
872*37da2899SCharles.Forsyth   {
873*37da2899SCharles.Forsyth     FT_Byte*   table     = cmap->data;
874*37da2899SCharles.Forsyth     FT_UInt32  result    = 0;
875*37da2899SCharles.Forsyth     FT_UInt32  char_code = *pchar_code + 1;
876*37da2899SCharles.Forsyth     FT_UInt    gindex    = 0;
877*37da2899SCharles.Forsyth     FT_Byte*   p;
878*37da2899SCharles.Forsyth     FT_Byte*   q;
879*37da2899SCharles.Forsyth     FT_UInt    code, num_segs2;
880*37da2899SCharles.Forsyth 
881*37da2899SCharles.Forsyth 
882*37da2899SCharles.Forsyth     if ( char_code >= 0x10000UL )
883*37da2899SCharles.Forsyth       goto Exit;
884*37da2899SCharles.Forsyth 
885*37da2899SCharles.Forsyth     code      = (FT_UInt)char_code;
886*37da2899SCharles.Forsyth     p         = table + 6;
887*37da2899SCharles.Forsyth     num_segs2 = TT_PEEK_USHORT(p) & -2;  /* ensure even-ness */
888*37da2899SCharles.Forsyth 
889*37da2899SCharles.Forsyth     for (;;)
890*37da2899SCharles.Forsyth     {
891*37da2899SCharles.Forsyth       FT_UInt  offset, n;
892*37da2899SCharles.Forsyth       FT_Int   delta;
893*37da2899SCharles.Forsyth 
894*37da2899SCharles.Forsyth 
895*37da2899SCharles.Forsyth       p = table + 14;              /* ends table  */
896*37da2899SCharles.Forsyth       q = table + 16 + num_segs2;  /* starts table */
897*37da2899SCharles.Forsyth 
898*37da2899SCharles.Forsyth       for ( n = 0; n < num_segs2; n += 2 )
899*37da2899SCharles.Forsyth       {
900*37da2899SCharles.Forsyth         FT_UInt  end   = TT_NEXT_USHORT( p );
901*37da2899SCharles.Forsyth         FT_UInt  start = TT_NEXT_USHORT( q );
902*37da2899SCharles.Forsyth 
903*37da2899SCharles.Forsyth 
904*37da2899SCharles.Forsyth         if ( code < start )
905*37da2899SCharles.Forsyth           code = start;
906*37da2899SCharles.Forsyth 
907*37da2899SCharles.Forsyth         if ( code <= end )
908*37da2899SCharles.Forsyth         {
909*37da2899SCharles.Forsyth           p = q + num_segs2 - 2;
910*37da2899SCharles.Forsyth           delta = TT_PEEK_SHORT( p );
911*37da2899SCharles.Forsyth           p += num_segs2;
912*37da2899SCharles.Forsyth           offset = TT_PEEK_USHORT( p );
913*37da2899SCharles.Forsyth 
914*37da2899SCharles.Forsyth           if ( offset != 0 && offset != 0xFFFFU )
915*37da2899SCharles.Forsyth           {
916*37da2899SCharles.Forsyth             /* parse the glyph ids array for non-0 index */
917*37da2899SCharles.Forsyth             p += offset + ( code - start ) * 2;
918*37da2899SCharles.Forsyth             while ( code <= end )
919*37da2899SCharles.Forsyth             {
920*37da2899SCharles.Forsyth               gindex = TT_NEXT_USHORT( p );
921*37da2899SCharles.Forsyth               if ( gindex != 0 )
922*37da2899SCharles.Forsyth               {
923*37da2899SCharles.Forsyth                 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
924*37da2899SCharles.Forsyth                 if ( gindex != 0 )
925*37da2899SCharles.Forsyth                   break;
926*37da2899SCharles.Forsyth               }
927*37da2899SCharles.Forsyth               code++;
928*37da2899SCharles.Forsyth             }
929*37da2899SCharles.Forsyth           }
930*37da2899SCharles.Forsyth           else if ( offset == 0xFFFFU )
931*37da2899SCharles.Forsyth           {
932*37da2899SCharles.Forsyth             /* an offset of 0xFFFF means an empty glyph in certain fonts! */
933*37da2899SCharles.Forsyth             code = end;
934*37da2899SCharles.Forsyth             break;
935*37da2899SCharles.Forsyth           }
936*37da2899SCharles.Forsyth           else
937*37da2899SCharles.Forsyth             gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
938*37da2899SCharles.Forsyth 
939*37da2899SCharles.Forsyth           if ( gindex == 0 )
940*37da2899SCharles.Forsyth             break;
941*37da2899SCharles.Forsyth 
942*37da2899SCharles.Forsyth           result = code;
943*37da2899SCharles.Forsyth           goto Exit;
944*37da2899SCharles.Forsyth         }
945*37da2899SCharles.Forsyth       }
946*37da2899SCharles.Forsyth 
947*37da2899SCharles.Forsyth       /* loop to next trial charcode */
948*37da2899SCharles.Forsyth       if ( code >= 0xFFFFU )
949*37da2899SCharles.Forsyth         break;
950*37da2899SCharles.Forsyth 
951*37da2899SCharles.Forsyth       code++;
952*37da2899SCharles.Forsyth     }
953*37da2899SCharles.Forsyth     return (FT_UInt)result;
954*37da2899SCharles.Forsyth 
955*37da2899SCharles.Forsyth   Exit:
956*37da2899SCharles.Forsyth     *pchar_code = result;
957*37da2899SCharles.Forsyth     return gindex;
958*37da2899SCharles.Forsyth   }
959*37da2899SCharles.Forsyth 
960*37da2899SCharles.Forsyth 
961*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
962*37da2899SCharles.Forsyth   const TT_CMap_ClassRec  tt_cmap4_class_rec =
963*37da2899SCharles.Forsyth   {
964*37da2899SCharles.Forsyth     {
965*37da2899SCharles.Forsyth       sizeof ( TT_CMapRec ),
966*37da2899SCharles.Forsyth 
967*37da2899SCharles.Forsyth       (FT_CMap_InitFunc)     tt_cmap_init,
968*37da2899SCharles.Forsyth       (FT_CMap_DoneFunc)     NULL,
969*37da2899SCharles.Forsyth       (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
970*37da2899SCharles.Forsyth       (FT_CMap_CharNextFunc) tt_cmap4_char_next
971*37da2899SCharles.Forsyth     },
972*37da2899SCharles.Forsyth     4,
973*37da2899SCharles.Forsyth     (TT_CMap_ValidateFunc)   tt_cmap4_validate
974*37da2899SCharles.Forsyth   };
975*37da2899SCharles.Forsyth 
976*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_4 */
977*37da2899SCharles.Forsyth 
978*37da2899SCharles.Forsyth 
979*37da2899SCharles.Forsyth   /*************************************************************************/
980*37da2899SCharles.Forsyth   /*************************************************************************/
981*37da2899SCharles.Forsyth   /*****                                                               *****/
982*37da2899SCharles.Forsyth   /*****                          FORMAT 6                             *****/
983*37da2899SCharles.Forsyth   /*****                                                               *****/
984*37da2899SCharles.Forsyth   /*************************************************************************/
985*37da2899SCharles.Forsyth   /*************************************************************************/
986*37da2899SCharles.Forsyth 
987*37da2899SCharles.Forsyth   /*************************************************************************/
988*37da2899SCharles.Forsyth   /*                                                                       */
989*37da2899SCharles.Forsyth   /* TABLE OVERVIEW                                                        */
990*37da2899SCharles.Forsyth   /* --------------                                                        */
991*37da2899SCharles.Forsyth   /*                                                                       */
992*37da2899SCharles.Forsyth   /*   NAME        OFFSET          TYPE             DESCRIPTION            */
993*37da2899SCharles.Forsyth   /*                                                                       */
994*37da2899SCharles.Forsyth   /*   format       0              USHORT           must be 4              */
995*37da2899SCharles.Forsyth   /*   length       2              USHORT           table length in bytes  */
996*37da2899SCharles.Forsyth   /*   language     4              USHORT           Mac language code      */
997*37da2899SCharles.Forsyth   /*                                                                       */
998*37da2899SCharles.Forsyth   /*   first        6              USHORT           first segment code     */
999*37da2899SCharles.Forsyth   /*   count        8              USHORT           segment size in chars  */
1000*37da2899SCharles.Forsyth   /*   glyphIds     10             USHORT[count]    glyph ids              */
1001*37da2899SCharles.Forsyth   /*                                                                       */
1002*37da2899SCharles.Forsyth   /* A very simplified segment mapping.                                    */
1003*37da2899SCharles.Forsyth   /*                                                                       */
1004*37da2899SCharles.Forsyth 
1005*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_6
1006*37da2899SCharles.Forsyth 
1007*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
tt_cmap6_validate(FT_Byte * table,FT_Validator valid)1008*37da2899SCharles.Forsyth   tt_cmap6_validate( FT_Byte*      table,
1009*37da2899SCharles.Forsyth                      FT_Validator  valid )
1010*37da2899SCharles.Forsyth   {
1011*37da2899SCharles.Forsyth     FT_Byte*  p;
1012*37da2899SCharles.Forsyth     FT_UInt   length, start, count;
1013*37da2899SCharles.Forsyth 
1014*37da2899SCharles.Forsyth 
1015*37da2899SCharles.Forsyth     if ( table + 10 > valid->limit )
1016*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1017*37da2899SCharles.Forsyth 
1018*37da2899SCharles.Forsyth     p      = table + 2;
1019*37da2899SCharles.Forsyth     length = TT_NEXT_USHORT( p );
1020*37da2899SCharles.Forsyth 
1021*37da2899SCharles.Forsyth     p      = table + 6;             /* skip language */
1022*37da2899SCharles.Forsyth     start  = TT_NEXT_USHORT( p );
1023*37da2899SCharles.Forsyth     count  = TT_NEXT_USHORT( p );
1024*37da2899SCharles.Forsyth 
1025*37da2899SCharles.Forsyth     if ( table + length > valid->limit || length < 10 + count * 2 )
1026*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1027*37da2899SCharles.Forsyth 
1028*37da2899SCharles.Forsyth     /* check glyph indices */
1029*37da2899SCharles.Forsyth     if ( valid->level >= FT_VALIDATE_TIGHT )
1030*37da2899SCharles.Forsyth     {
1031*37da2899SCharles.Forsyth       FT_UInt  gindex;
1032*37da2899SCharles.Forsyth 
1033*37da2899SCharles.Forsyth 
1034*37da2899SCharles.Forsyth       for ( ; count > 0; count-- )
1035*37da2899SCharles.Forsyth       {
1036*37da2899SCharles.Forsyth         gindex = TT_NEXT_USHORT( p );
1037*37da2899SCharles.Forsyth         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1038*37da2899SCharles.Forsyth           FT_INVALID_GLYPH_ID;
1039*37da2899SCharles.Forsyth       }
1040*37da2899SCharles.Forsyth     }
1041*37da2899SCharles.Forsyth   }
1042*37da2899SCharles.Forsyth 
1043*37da2899SCharles.Forsyth 
1044*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap6_char_index(TT_CMap cmap,FT_UInt32 char_code)1045*37da2899SCharles.Forsyth   tt_cmap6_char_index( TT_CMap    cmap,
1046*37da2899SCharles.Forsyth                        FT_UInt32  char_code )
1047*37da2899SCharles.Forsyth   {
1048*37da2899SCharles.Forsyth     FT_Byte*  table  = cmap->data;
1049*37da2899SCharles.Forsyth     FT_UInt   result = 0;
1050*37da2899SCharles.Forsyth     FT_Byte*  p      = table + 6;
1051*37da2899SCharles.Forsyth     FT_UInt   start  = TT_NEXT_USHORT( p );
1052*37da2899SCharles.Forsyth     FT_UInt   count  = TT_NEXT_USHORT( p );
1053*37da2899SCharles.Forsyth     FT_UInt   idx    = (FT_UInt)( char_code - start );
1054*37da2899SCharles.Forsyth 
1055*37da2899SCharles.Forsyth 
1056*37da2899SCharles.Forsyth     if ( idx < count )
1057*37da2899SCharles.Forsyth     {
1058*37da2899SCharles.Forsyth       p += 2 * idx;
1059*37da2899SCharles.Forsyth       result = TT_PEEK_USHORT( p );
1060*37da2899SCharles.Forsyth     }
1061*37da2899SCharles.Forsyth     return result;
1062*37da2899SCharles.Forsyth   }
1063*37da2899SCharles.Forsyth 
1064*37da2899SCharles.Forsyth 
1065*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap6_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1066*37da2899SCharles.Forsyth   tt_cmap6_char_next( TT_CMap     cmap,
1067*37da2899SCharles.Forsyth                       FT_UInt32  *pchar_code )
1068*37da2899SCharles.Forsyth   {
1069*37da2899SCharles.Forsyth     FT_Byte*   table     = cmap->data;
1070*37da2899SCharles.Forsyth     FT_UInt32  result    = 0;
1071*37da2899SCharles.Forsyth     FT_UInt32  char_code = *pchar_code + 1;
1072*37da2899SCharles.Forsyth     FT_UInt    gindex    = 0;
1073*37da2899SCharles.Forsyth 
1074*37da2899SCharles.Forsyth     FT_Byte*   p         = table + 6;
1075*37da2899SCharles.Forsyth     FT_UInt    start     = TT_NEXT_USHORT( p );
1076*37da2899SCharles.Forsyth     FT_UInt    count     = TT_NEXT_USHORT( p );
1077*37da2899SCharles.Forsyth     FT_UInt    idx;
1078*37da2899SCharles.Forsyth 
1079*37da2899SCharles.Forsyth 
1080*37da2899SCharles.Forsyth     if ( char_code >= 0x10000UL )
1081*37da2899SCharles.Forsyth       goto Exit;
1082*37da2899SCharles.Forsyth 
1083*37da2899SCharles.Forsyth     if ( char_code < start )
1084*37da2899SCharles.Forsyth       char_code = start;
1085*37da2899SCharles.Forsyth 
1086*37da2899SCharles.Forsyth     idx = (FT_UInt)( char_code - start );
1087*37da2899SCharles.Forsyth     p  += 2 * idx;
1088*37da2899SCharles.Forsyth 
1089*37da2899SCharles.Forsyth     for ( ; idx < count; idx++ )
1090*37da2899SCharles.Forsyth     {
1091*37da2899SCharles.Forsyth       gindex = TT_NEXT_USHORT( p );
1092*37da2899SCharles.Forsyth       if ( gindex != 0 )
1093*37da2899SCharles.Forsyth       {
1094*37da2899SCharles.Forsyth         result = char_code;
1095*37da2899SCharles.Forsyth         break;
1096*37da2899SCharles.Forsyth       }
1097*37da2899SCharles.Forsyth       char_code++;
1098*37da2899SCharles.Forsyth     }
1099*37da2899SCharles.Forsyth 
1100*37da2899SCharles.Forsyth   Exit:
1101*37da2899SCharles.Forsyth     *pchar_code = result;
1102*37da2899SCharles.Forsyth     return gindex;
1103*37da2899SCharles.Forsyth   }
1104*37da2899SCharles.Forsyth 
1105*37da2899SCharles.Forsyth 
1106*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
1107*37da2899SCharles.Forsyth   const TT_CMap_ClassRec  tt_cmap6_class_rec =
1108*37da2899SCharles.Forsyth   {
1109*37da2899SCharles.Forsyth     {
1110*37da2899SCharles.Forsyth       sizeof ( TT_CMapRec ),
1111*37da2899SCharles.Forsyth 
1112*37da2899SCharles.Forsyth       (FT_CMap_InitFunc)     tt_cmap_init,
1113*37da2899SCharles.Forsyth       (FT_CMap_DoneFunc)     NULL,
1114*37da2899SCharles.Forsyth       (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
1115*37da2899SCharles.Forsyth       (FT_CMap_CharNextFunc) tt_cmap6_char_next
1116*37da2899SCharles.Forsyth     },
1117*37da2899SCharles.Forsyth     6,
1118*37da2899SCharles.Forsyth     (TT_CMap_ValidateFunc)   tt_cmap6_validate
1119*37da2899SCharles.Forsyth   };
1120*37da2899SCharles.Forsyth 
1121*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_6 */
1122*37da2899SCharles.Forsyth 
1123*37da2899SCharles.Forsyth 
1124*37da2899SCharles.Forsyth   /*************************************************************************/
1125*37da2899SCharles.Forsyth   /*************************************************************************/
1126*37da2899SCharles.Forsyth   /*****                                                               *****/
1127*37da2899SCharles.Forsyth   /*****                          FORMAT 8                             *****/
1128*37da2899SCharles.Forsyth   /*****                                                               *****/
1129*37da2899SCharles.Forsyth   /***** It's hard to completely understand what the OpenType spec     *****/
1130*37da2899SCharles.Forsyth   /***** says about this format, but here is my conclusion.            *****/
1131*37da2899SCharles.Forsyth   /*****                                                               *****/
1132*37da2899SCharles.Forsyth   /***** The purpose of this format is to easily map UTF-16 text to    *****/
1133*37da2899SCharles.Forsyth   /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
1134*37da2899SCharles.Forsyth   /***** the following formats:                                        *****/
1135*37da2899SCharles.Forsyth   /*****                                                               *****/
1136*37da2899SCharles.Forsyth   /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
1137*37da2899SCharles.Forsyth   /*****     Area (i.e. U+D800-U+DFFF).                                *****/
1138*37da2899SCharles.Forsyth   /*****                                                               *****/
1139*37da2899SCharles.Forsyth   /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
1140*37da2899SCharles.Forsyth   /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
1141*37da2899SCharles.Forsyth   /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
1142*37da2899SCharles.Forsyth   /*****      Area.                                                    *****/
1143*37da2899SCharles.Forsyth   /*****                                                               *****/
1144*37da2899SCharles.Forsyth   /***** The 'is32' table embedded in the charmap indicates whether a  *****/
1145*37da2899SCharles.Forsyth   /***** given 16-bit value is in the surrogates area or not.          *****/
1146*37da2899SCharles.Forsyth   /*****                                                               *****/
1147*37da2899SCharles.Forsyth   /***** So, for any given `char_code', we can assert the following:   *****/
1148*37da2899SCharles.Forsyth   /*****                                                               *****/
1149*37da2899SCharles.Forsyth   /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
1150*37da2899SCharles.Forsyth   /*****                                                               *****/
1151*37da2899SCharles.Forsyth   /*****   If `char_hi != 0' then we must have both                    *****/
1152*37da2899SCharles.Forsyth   /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
1153*37da2899SCharles.Forsyth   /*****                                                               *****/
1154*37da2899SCharles.Forsyth   /*************************************************************************/
1155*37da2899SCharles.Forsyth   /*************************************************************************/
1156*37da2899SCharles.Forsyth 
1157*37da2899SCharles.Forsyth   /*************************************************************************/
1158*37da2899SCharles.Forsyth   /*                                                                       */
1159*37da2899SCharles.Forsyth   /* TABLE OVERVIEW                                                        */
1160*37da2899SCharles.Forsyth   /* --------------                                                        */
1161*37da2899SCharles.Forsyth   /*                                                                       */
1162*37da2899SCharles.Forsyth   /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
1163*37da2899SCharles.Forsyth   /*                                                                       */
1164*37da2899SCharles.Forsyth   /*   format      0              USHORT      must be 8                    */
1165*37da2899SCharles.Forsyth   /*   reseved     2              USHORT      reserved                     */
1166*37da2899SCharles.Forsyth   /*   length      4              ULONG       length in bytes              */
1167*37da2899SCharles.Forsyth   /*   language    8              ULONG       Mac language code            */
1168*37da2899SCharles.Forsyth   /*   is32        12             BYTE[8192]  32-bitness bitmap            */
1169*37da2899SCharles.Forsyth   /*   count       8204           ULONG       number of groups             */
1170*37da2899SCharles.Forsyth   /*                                                                       */
1171*37da2899SCharles.Forsyth   /* This header is followed by 'count' groups of the following format:    */
1172*37da2899SCharles.Forsyth   /*                                                                       */
1173*37da2899SCharles.Forsyth   /*   start       0              ULONG       first charcode               */
1174*37da2899SCharles.Forsyth   /*   end         4              ULONG       last charcode                */
1175*37da2899SCharles.Forsyth   /*   startId     8              ULONG       start glyph id for the group */
1176*37da2899SCharles.Forsyth   /*                                                                       */
1177*37da2899SCharles.Forsyth 
1178*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_8
1179*37da2899SCharles.Forsyth 
1180*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
tt_cmap8_validate(FT_Byte * table,FT_Validator valid)1181*37da2899SCharles.Forsyth   tt_cmap8_validate( FT_Byte*      table,
1182*37da2899SCharles.Forsyth                      FT_Validator  valid )
1183*37da2899SCharles.Forsyth   {
1184*37da2899SCharles.Forsyth     FT_Byte*   p = table + 4;
1185*37da2899SCharles.Forsyth     FT_Byte*   is32;
1186*37da2899SCharles.Forsyth     FT_UInt32  length;
1187*37da2899SCharles.Forsyth     FT_UInt32  num_groups;
1188*37da2899SCharles.Forsyth 
1189*37da2899SCharles.Forsyth 
1190*37da2899SCharles.Forsyth     if ( table + 16 + 8192 > valid->limit )
1191*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1192*37da2899SCharles.Forsyth 
1193*37da2899SCharles.Forsyth     length = TT_NEXT_ULONG( p );
1194*37da2899SCharles.Forsyth     if ( table + length > valid->limit || length < 8208 )
1195*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1196*37da2899SCharles.Forsyth 
1197*37da2899SCharles.Forsyth     is32       = table + 12;
1198*37da2899SCharles.Forsyth     p          = is32  + 8192;          /* skip `is32' array */
1199*37da2899SCharles.Forsyth     num_groups = TT_NEXT_ULONG( p );
1200*37da2899SCharles.Forsyth 
1201*37da2899SCharles.Forsyth     if ( p + num_groups * 12 > valid->limit )
1202*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1203*37da2899SCharles.Forsyth 
1204*37da2899SCharles.Forsyth     /* check groups, they must be in increasing order */
1205*37da2899SCharles.Forsyth     {
1206*37da2899SCharles.Forsyth       FT_UInt32  n, start, end, start_id, count, last = 0;
1207*37da2899SCharles.Forsyth 
1208*37da2899SCharles.Forsyth 
1209*37da2899SCharles.Forsyth       for ( n = 0; n < num_groups; n++ )
1210*37da2899SCharles.Forsyth       {
1211*37da2899SCharles.Forsyth         FT_UInt   hi, lo;
1212*37da2899SCharles.Forsyth 
1213*37da2899SCharles.Forsyth 
1214*37da2899SCharles.Forsyth         start    = TT_NEXT_ULONG( p );
1215*37da2899SCharles.Forsyth         end      = TT_NEXT_ULONG( p );
1216*37da2899SCharles.Forsyth         start_id = TT_NEXT_ULONG( p );
1217*37da2899SCharles.Forsyth 
1218*37da2899SCharles.Forsyth         if ( start > end )
1219*37da2899SCharles.Forsyth           FT_INVALID_DATA;
1220*37da2899SCharles.Forsyth 
1221*37da2899SCharles.Forsyth         if ( n > 0 && start <= last )
1222*37da2899SCharles.Forsyth           FT_INVALID_DATA;
1223*37da2899SCharles.Forsyth 
1224*37da2899SCharles.Forsyth         if ( valid->level >= FT_VALIDATE_TIGHT )
1225*37da2899SCharles.Forsyth         {
1226*37da2899SCharles.Forsyth           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1227*37da2899SCharles.Forsyth             FT_INVALID_GLYPH_ID;
1228*37da2899SCharles.Forsyth 
1229*37da2899SCharles.Forsyth           count = (FT_UInt32)( end - start + 1 );
1230*37da2899SCharles.Forsyth 
1231*37da2899SCharles.Forsyth           if ( start & ~0xFFFFU )
1232*37da2899SCharles.Forsyth           {
1233*37da2899SCharles.Forsyth             /* start_hi != 0; check that is32[i] is 1 for each i in */
1234*37da2899SCharles.Forsyth             /* the `hi' and `lo' of the range [start..end]          */
1235*37da2899SCharles.Forsyth             for ( ; count > 0; count--, start++ )
1236*37da2899SCharles.Forsyth             {
1237*37da2899SCharles.Forsyth               hi = (FT_UInt)( start >> 16 );
1238*37da2899SCharles.Forsyth               lo = (FT_UInt)( start & 0xFFFFU );
1239*37da2899SCharles.Forsyth 
1240*37da2899SCharles.Forsyth               if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1241*37da2899SCharles.Forsyth                 FT_INVALID_DATA;
1242*37da2899SCharles.Forsyth 
1243*37da2899SCharles.Forsyth               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1244*37da2899SCharles.Forsyth                 FT_INVALID_DATA;
1245*37da2899SCharles.Forsyth             }
1246*37da2899SCharles.Forsyth           }
1247*37da2899SCharles.Forsyth           else
1248*37da2899SCharles.Forsyth           {
1249*37da2899SCharles.Forsyth             /* start_hi == 0; check that is32[i] is 0 for each i in */
1250*37da2899SCharles.Forsyth             /* the range [start..end]                               */
1251*37da2899SCharles.Forsyth 
1252*37da2899SCharles.Forsyth             /* end_hi cannot be != 0! */
1253*37da2899SCharles.Forsyth             if ( end & ~0xFFFFU )
1254*37da2899SCharles.Forsyth               FT_INVALID_DATA;
1255*37da2899SCharles.Forsyth 
1256*37da2899SCharles.Forsyth             for ( ; count > 0; count--, start++ )
1257*37da2899SCharles.Forsyth             {
1258*37da2899SCharles.Forsyth               lo = (FT_UInt)( start & 0xFFFFU );
1259*37da2899SCharles.Forsyth 
1260*37da2899SCharles.Forsyth               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1261*37da2899SCharles.Forsyth                 FT_INVALID_DATA;
1262*37da2899SCharles.Forsyth             }
1263*37da2899SCharles.Forsyth           }
1264*37da2899SCharles.Forsyth         }
1265*37da2899SCharles.Forsyth 
1266*37da2899SCharles.Forsyth         last = end;
1267*37da2899SCharles.Forsyth       }
1268*37da2899SCharles.Forsyth     }
1269*37da2899SCharles.Forsyth   }
1270*37da2899SCharles.Forsyth 
1271*37da2899SCharles.Forsyth 
1272*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap8_char_index(TT_CMap cmap,FT_UInt32 char_code)1273*37da2899SCharles.Forsyth   tt_cmap8_char_index( TT_CMap    cmap,
1274*37da2899SCharles.Forsyth                        FT_UInt32  char_code )
1275*37da2899SCharles.Forsyth   {
1276*37da2899SCharles.Forsyth     FT_Byte*   table      = cmap->data;
1277*37da2899SCharles.Forsyth     FT_UInt    result     = 0;
1278*37da2899SCharles.Forsyth     FT_Byte*   p          = table + 8204;
1279*37da2899SCharles.Forsyth     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1280*37da2899SCharles.Forsyth     FT_UInt32  start, end, start_id;
1281*37da2899SCharles.Forsyth 
1282*37da2899SCharles.Forsyth 
1283*37da2899SCharles.Forsyth     for ( ; num_groups > 0; num_groups-- )
1284*37da2899SCharles.Forsyth     {
1285*37da2899SCharles.Forsyth       start    = TT_NEXT_ULONG( p );
1286*37da2899SCharles.Forsyth       end      = TT_NEXT_ULONG( p );
1287*37da2899SCharles.Forsyth       start_id = TT_NEXT_ULONG( p );
1288*37da2899SCharles.Forsyth 
1289*37da2899SCharles.Forsyth       if ( char_code < start )
1290*37da2899SCharles.Forsyth         break;
1291*37da2899SCharles.Forsyth 
1292*37da2899SCharles.Forsyth       if ( char_code <= end )
1293*37da2899SCharles.Forsyth       {
1294*37da2899SCharles.Forsyth         result = (FT_UInt)( start_id + char_code - start );
1295*37da2899SCharles.Forsyth         break;
1296*37da2899SCharles.Forsyth       }
1297*37da2899SCharles.Forsyth     }
1298*37da2899SCharles.Forsyth     return result;
1299*37da2899SCharles.Forsyth   }
1300*37da2899SCharles.Forsyth 
1301*37da2899SCharles.Forsyth 
1302*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap8_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1303*37da2899SCharles.Forsyth   tt_cmap8_char_next( TT_CMap     cmap,
1304*37da2899SCharles.Forsyth                       FT_UInt32  *pchar_code )
1305*37da2899SCharles.Forsyth   {
1306*37da2899SCharles.Forsyth     FT_UInt32  result     = 0;
1307*37da2899SCharles.Forsyth     FT_UInt32  char_code  = *pchar_code + 1;
1308*37da2899SCharles.Forsyth     FT_UInt    gindex     = 0;
1309*37da2899SCharles.Forsyth     FT_Byte*   table      = cmap->data;
1310*37da2899SCharles.Forsyth     FT_Byte*   p          = table + 8204;
1311*37da2899SCharles.Forsyth     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1312*37da2899SCharles.Forsyth     FT_UInt32  start, end, start_id;
1313*37da2899SCharles.Forsyth 
1314*37da2899SCharles.Forsyth 
1315*37da2899SCharles.Forsyth     p = table + 8208;
1316*37da2899SCharles.Forsyth 
1317*37da2899SCharles.Forsyth     for ( ; num_groups > 0; num_groups-- )
1318*37da2899SCharles.Forsyth     {
1319*37da2899SCharles.Forsyth       start    = TT_NEXT_ULONG( p );
1320*37da2899SCharles.Forsyth       end      = TT_NEXT_ULONG( p );
1321*37da2899SCharles.Forsyth       start_id = TT_NEXT_ULONG( p );
1322*37da2899SCharles.Forsyth 
1323*37da2899SCharles.Forsyth       if ( char_code < start )
1324*37da2899SCharles.Forsyth         char_code = start;
1325*37da2899SCharles.Forsyth 
1326*37da2899SCharles.Forsyth       if ( char_code <= end )
1327*37da2899SCharles.Forsyth       {
1328*37da2899SCharles.Forsyth         gindex = (FT_UInt)( char_code - start + start_id );
1329*37da2899SCharles.Forsyth         if ( gindex != 0 )
1330*37da2899SCharles.Forsyth         {
1331*37da2899SCharles.Forsyth           result = char_code;
1332*37da2899SCharles.Forsyth           goto Exit;
1333*37da2899SCharles.Forsyth         }
1334*37da2899SCharles.Forsyth       }
1335*37da2899SCharles.Forsyth     }
1336*37da2899SCharles.Forsyth 
1337*37da2899SCharles.Forsyth   Exit:
1338*37da2899SCharles.Forsyth     *pchar_code = result;
1339*37da2899SCharles.Forsyth     return gindex;
1340*37da2899SCharles.Forsyth   }
1341*37da2899SCharles.Forsyth 
1342*37da2899SCharles.Forsyth 
1343*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
1344*37da2899SCharles.Forsyth   const TT_CMap_ClassRec  tt_cmap8_class_rec =
1345*37da2899SCharles.Forsyth   {
1346*37da2899SCharles.Forsyth     {
1347*37da2899SCharles.Forsyth       sizeof ( TT_CMapRec ),
1348*37da2899SCharles.Forsyth 
1349*37da2899SCharles.Forsyth       (FT_CMap_InitFunc)     tt_cmap_init,
1350*37da2899SCharles.Forsyth       (FT_CMap_DoneFunc)     NULL,
1351*37da2899SCharles.Forsyth       (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1352*37da2899SCharles.Forsyth       (FT_CMap_CharNextFunc) tt_cmap8_char_next
1353*37da2899SCharles.Forsyth     },
1354*37da2899SCharles.Forsyth     8,
1355*37da2899SCharles.Forsyth     (TT_CMap_ValidateFunc)   tt_cmap8_validate
1356*37da2899SCharles.Forsyth   };
1357*37da2899SCharles.Forsyth 
1358*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_8 */
1359*37da2899SCharles.Forsyth 
1360*37da2899SCharles.Forsyth 
1361*37da2899SCharles.Forsyth   /*************************************************************************/
1362*37da2899SCharles.Forsyth   /*************************************************************************/
1363*37da2899SCharles.Forsyth   /*****                                                               *****/
1364*37da2899SCharles.Forsyth   /*****                          FORMAT 10                            *****/
1365*37da2899SCharles.Forsyth   /*****                                                               *****/
1366*37da2899SCharles.Forsyth   /*************************************************************************/
1367*37da2899SCharles.Forsyth   /*************************************************************************/
1368*37da2899SCharles.Forsyth 
1369*37da2899SCharles.Forsyth   /*************************************************************************/
1370*37da2899SCharles.Forsyth   /*                                                                       */
1371*37da2899SCharles.Forsyth   /* TABLE OVERVIEW                                                        */
1372*37da2899SCharles.Forsyth   /* --------------                                                        */
1373*37da2899SCharles.Forsyth   /*                                                                       */
1374*37da2899SCharles.Forsyth   /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
1375*37da2899SCharles.Forsyth   /*                                                                       */
1376*37da2899SCharles.Forsyth   /*   format     0      USHORT             must be 10                     */
1377*37da2899SCharles.Forsyth   /*   reserved   2      USHORT             reserved                       */
1378*37da2899SCharles.Forsyth   /*   length     4      ULONG              length in bytes                */
1379*37da2899SCharles.Forsyth   /*   language   8      ULONG              Mac language code              */
1380*37da2899SCharles.Forsyth   /*                                                                       */
1381*37da2899SCharles.Forsyth   /*   start     12      ULONG              first char in range            */
1382*37da2899SCharles.Forsyth   /*   count     16      ULONG              number of chars in range       */
1383*37da2899SCharles.Forsyth   /*   glyphIds  20      USHORT[count]      glyph indices covered          */
1384*37da2899SCharles.Forsyth   /*                                                                       */
1385*37da2899SCharles.Forsyth 
1386*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_10
1387*37da2899SCharles.Forsyth 
1388*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
tt_cmap10_validate(FT_Byte * table,FT_Validator valid)1389*37da2899SCharles.Forsyth   tt_cmap10_validate( FT_Byte*      table,
1390*37da2899SCharles.Forsyth                       FT_Validator  valid )
1391*37da2899SCharles.Forsyth   {
1392*37da2899SCharles.Forsyth     FT_Byte*  p = table + 4;
1393*37da2899SCharles.Forsyth     FT_ULong  length, start, count;
1394*37da2899SCharles.Forsyth 
1395*37da2899SCharles.Forsyth 
1396*37da2899SCharles.Forsyth     if ( table + 20 > valid->limit )
1397*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1398*37da2899SCharles.Forsyth 
1399*37da2899SCharles.Forsyth     length = TT_NEXT_ULONG( p );
1400*37da2899SCharles.Forsyth     p      = table + 12;
1401*37da2899SCharles.Forsyth     start  = TT_NEXT_ULONG( p );
1402*37da2899SCharles.Forsyth     count  = TT_NEXT_ULONG( p );
1403*37da2899SCharles.Forsyth 
1404*37da2899SCharles.Forsyth     if ( table + length > valid->limit || length < 20 + count * 2 )
1405*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1406*37da2899SCharles.Forsyth 
1407*37da2899SCharles.Forsyth     /* check glyph indices */
1408*37da2899SCharles.Forsyth     if ( valid->level >= FT_VALIDATE_TIGHT )
1409*37da2899SCharles.Forsyth     {
1410*37da2899SCharles.Forsyth       FT_UInt  gindex;
1411*37da2899SCharles.Forsyth 
1412*37da2899SCharles.Forsyth 
1413*37da2899SCharles.Forsyth       for ( ; count > 0; count-- )
1414*37da2899SCharles.Forsyth       {
1415*37da2899SCharles.Forsyth         gindex = TT_NEXT_USHORT( p );
1416*37da2899SCharles.Forsyth         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1417*37da2899SCharles.Forsyth           FT_INVALID_GLYPH_ID;
1418*37da2899SCharles.Forsyth       }
1419*37da2899SCharles.Forsyth     }
1420*37da2899SCharles.Forsyth   }
1421*37da2899SCharles.Forsyth 
1422*37da2899SCharles.Forsyth 
1423*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap10_char_index(TT_CMap cmap,FT_UInt32 char_code)1424*37da2899SCharles.Forsyth   tt_cmap10_char_index( TT_CMap    cmap,
1425*37da2899SCharles.Forsyth                         FT_UInt32  char_code )
1426*37da2899SCharles.Forsyth   {
1427*37da2899SCharles.Forsyth     FT_Byte*   table  = cmap->data;
1428*37da2899SCharles.Forsyth     FT_UInt    result = 0;
1429*37da2899SCharles.Forsyth     FT_Byte*   p      = table + 12;
1430*37da2899SCharles.Forsyth     FT_UInt32  start  = TT_NEXT_ULONG( p );
1431*37da2899SCharles.Forsyth     FT_UInt32  count  = TT_NEXT_ULONG( p );
1432*37da2899SCharles.Forsyth     FT_UInt32  idx    = (FT_ULong)( char_code - start );
1433*37da2899SCharles.Forsyth 
1434*37da2899SCharles.Forsyth 
1435*37da2899SCharles.Forsyth     if ( idx < count )
1436*37da2899SCharles.Forsyth     {
1437*37da2899SCharles.Forsyth       p     += 2 * idx;
1438*37da2899SCharles.Forsyth       result = TT_PEEK_USHORT( p );
1439*37da2899SCharles.Forsyth     }
1440*37da2899SCharles.Forsyth     return result;
1441*37da2899SCharles.Forsyth   }
1442*37da2899SCharles.Forsyth 
1443*37da2899SCharles.Forsyth 
1444*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap10_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1445*37da2899SCharles.Forsyth   tt_cmap10_char_next( TT_CMap     cmap,
1446*37da2899SCharles.Forsyth                        FT_UInt32  *pchar_code )
1447*37da2899SCharles.Forsyth   {
1448*37da2899SCharles.Forsyth     FT_Byte*   table     = cmap->data;
1449*37da2899SCharles.Forsyth     FT_UInt32  result    = 0;
1450*37da2899SCharles.Forsyth     FT_UInt32  char_code = *pchar_code + 1;
1451*37da2899SCharles.Forsyth     FT_UInt    gindex    = 0;
1452*37da2899SCharles.Forsyth     FT_Byte*   p         = table + 12;
1453*37da2899SCharles.Forsyth     FT_UInt32  start     = TT_NEXT_ULONG( p );
1454*37da2899SCharles.Forsyth     FT_UInt32  count     = TT_NEXT_ULONG( p );
1455*37da2899SCharles.Forsyth     FT_UInt32  idx;
1456*37da2899SCharles.Forsyth 
1457*37da2899SCharles.Forsyth 
1458*37da2899SCharles.Forsyth     if ( char_code < start )
1459*37da2899SCharles.Forsyth       char_code = start;
1460*37da2899SCharles.Forsyth 
1461*37da2899SCharles.Forsyth     idx = (FT_UInt32)( char_code - start );
1462*37da2899SCharles.Forsyth     p  += 2 * idx;
1463*37da2899SCharles.Forsyth 
1464*37da2899SCharles.Forsyth     for ( ; idx < count; idx++ )
1465*37da2899SCharles.Forsyth     {
1466*37da2899SCharles.Forsyth       gindex = TT_NEXT_USHORT( p );
1467*37da2899SCharles.Forsyth       if ( gindex != 0 )
1468*37da2899SCharles.Forsyth       {
1469*37da2899SCharles.Forsyth         result = char_code;
1470*37da2899SCharles.Forsyth         break;
1471*37da2899SCharles.Forsyth       }
1472*37da2899SCharles.Forsyth       char_code++;
1473*37da2899SCharles.Forsyth     }
1474*37da2899SCharles.Forsyth 
1475*37da2899SCharles.Forsyth     *pchar_code = char_code;
1476*37da2899SCharles.Forsyth     return gindex;
1477*37da2899SCharles.Forsyth   }
1478*37da2899SCharles.Forsyth 
1479*37da2899SCharles.Forsyth 
1480*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
1481*37da2899SCharles.Forsyth   const TT_CMap_ClassRec  tt_cmap10_class_rec =
1482*37da2899SCharles.Forsyth   {
1483*37da2899SCharles.Forsyth     {
1484*37da2899SCharles.Forsyth       sizeof ( TT_CMapRec ),
1485*37da2899SCharles.Forsyth 
1486*37da2899SCharles.Forsyth       (FT_CMap_InitFunc)     tt_cmap_init,
1487*37da2899SCharles.Forsyth       (FT_CMap_DoneFunc)     NULL,
1488*37da2899SCharles.Forsyth       (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1489*37da2899SCharles.Forsyth       (FT_CMap_CharNextFunc) tt_cmap10_char_next
1490*37da2899SCharles.Forsyth     },
1491*37da2899SCharles.Forsyth     10,
1492*37da2899SCharles.Forsyth     (TT_CMap_ValidateFunc)   tt_cmap10_validate
1493*37da2899SCharles.Forsyth   };
1494*37da2899SCharles.Forsyth 
1495*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_10 */
1496*37da2899SCharles.Forsyth 
1497*37da2899SCharles.Forsyth 
1498*37da2899SCharles.Forsyth   /*************************************************************************/
1499*37da2899SCharles.Forsyth   /*************************************************************************/
1500*37da2899SCharles.Forsyth   /*****                                                               *****/
1501*37da2899SCharles.Forsyth   /*****                          FORMAT 12                            *****/
1502*37da2899SCharles.Forsyth   /*****                                                               *****/
1503*37da2899SCharles.Forsyth   /*************************************************************************/
1504*37da2899SCharles.Forsyth   /*************************************************************************/
1505*37da2899SCharles.Forsyth 
1506*37da2899SCharles.Forsyth   /*************************************************************************/
1507*37da2899SCharles.Forsyth   /*                                                                       */
1508*37da2899SCharles.Forsyth   /* TABLE OVERVIEW                                                        */
1509*37da2899SCharles.Forsyth   /* --------------                                                        */
1510*37da2899SCharles.Forsyth   /*                                                                       */
1511*37da2899SCharles.Forsyth   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
1512*37da2899SCharles.Forsyth   /*                                                                       */
1513*37da2899SCharles.Forsyth   /*   format      0          USHORT     must be 12                        */
1514*37da2899SCharles.Forsyth   /*   reserved    2          USHORT     reserved                          */
1515*37da2899SCharles.Forsyth   /*   length      4          ULONG      length in bytes                   */
1516*37da2899SCharles.Forsyth   /*   language    8          ULONG      Mac language code                 */
1517*37da2899SCharles.Forsyth   /*   count       12         ULONG      number of groups                  */
1518*37da2899SCharles.Forsyth   /*               16                                                      */
1519*37da2899SCharles.Forsyth   /*                                                                       */
1520*37da2899SCharles.Forsyth   /* This header is followed by `count' groups of the following format:    */
1521*37da2899SCharles.Forsyth   /*                                                                       */
1522*37da2899SCharles.Forsyth   /*   start       0          ULONG      first charcode                    */
1523*37da2899SCharles.Forsyth   /*   end         4          ULONG      last charcode                     */
1524*37da2899SCharles.Forsyth   /*   startId     8          ULONG      start glyph id for the group      */
1525*37da2899SCharles.Forsyth   /*                                                                       */
1526*37da2899SCharles.Forsyth 
1527*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_12
1528*37da2899SCharles.Forsyth 
1529*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
tt_cmap12_validate(FT_Byte * table,FT_Validator valid)1530*37da2899SCharles.Forsyth   tt_cmap12_validate( FT_Byte*      table,
1531*37da2899SCharles.Forsyth                       FT_Validator  valid )
1532*37da2899SCharles.Forsyth   {
1533*37da2899SCharles.Forsyth     FT_Byte*   p;
1534*37da2899SCharles.Forsyth     FT_ULong   length;
1535*37da2899SCharles.Forsyth     FT_ULong   num_groups;
1536*37da2899SCharles.Forsyth 
1537*37da2899SCharles.Forsyth 
1538*37da2899SCharles.Forsyth     if ( table + 16 > valid->limit )
1539*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1540*37da2899SCharles.Forsyth 
1541*37da2899SCharles.Forsyth     p      = table + 4;
1542*37da2899SCharles.Forsyth     length = TT_NEXT_ULONG( p );
1543*37da2899SCharles.Forsyth 
1544*37da2899SCharles.Forsyth     p          = table + 12;
1545*37da2899SCharles.Forsyth     num_groups = TT_NEXT_ULONG( p );
1546*37da2899SCharles.Forsyth 
1547*37da2899SCharles.Forsyth     if ( table + length > valid->limit || length < 16 + 12 * num_groups )
1548*37da2899SCharles.Forsyth       FT_INVALID_TOO_SHORT;
1549*37da2899SCharles.Forsyth 
1550*37da2899SCharles.Forsyth     /* check groups, they must be in increasing order */
1551*37da2899SCharles.Forsyth     {
1552*37da2899SCharles.Forsyth       FT_ULong  n, start, end, start_id, last = 0;
1553*37da2899SCharles.Forsyth 
1554*37da2899SCharles.Forsyth 
1555*37da2899SCharles.Forsyth       for ( n = 0; n < num_groups; n++ )
1556*37da2899SCharles.Forsyth       {
1557*37da2899SCharles.Forsyth         start    = TT_NEXT_ULONG( p );
1558*37da2899SCharles.Forsyth         end      = TT_NEXT_ULONG( p );
1559*37da2899SCharles.Forsyth         start_id = TT_NEXT_ULONG( p );
1560*37da2899SCharles.Forsyth 
1561*37da2899SCharles.Forsyth         if ( start > end )
1562*37da2899SCharles.Forsyth           FT_INVALID_DATA;
1563*37da2899SCharles.Forsyth 
1564*37da2899SCharles.Forsyth         if ( n > 0 && start <= last )
1565*37da2899SCharles.Forsyth           FT_INVALID_DATA;
1566*37da2899SCharles.Forsyth 
1567*37da2899SCharles.Forsyth         if ( valid->level >= FT_VALIDATE_TIGHT )
1568*37da2899SCharles.Forsyth         {
1569*37da2899SCharles.Forsyth           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1570*37da2899SCharles.Forsyth             FT_INVALID_GLYPH_ID;
1571*37da2899SCharles.Forsyth         }
1572*37da2899SCharles.Forsyth 
1573*37da2899SCharles.Forsyth         last = end;
1574*37da2899SCharles.Forsyth       }
1575*37da2899SCharles.Forsyth     }
1576*37da2899SCharles.Forsyth   }
1577*37da2899SCharles.Forsyth 
1578*37da2899SCharles.Forsyth 
1579*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap12_char_index(TT_CMap cmap,FT_UInt32 char_code)1580*37da2899SCharles.Forsyth   tt_cmap12_char_index( TT_CMap    cmap,
1581*37da2899SCharles.Forsyth                         FT_UInt32  char_code )
1582*37da2899SCharles.Forsyth   {
1583*37da2899SCharles.Forsyth     FT_UInt    result     = 0;
1584*37da2899SCharles.Forsyth     FT_Byte*   table      = cmap->data;
1585*37da2899SCharles.Forsyth     FT_Byte*   p          = table + 12;
1586*37da2899SCharles.Forsyth     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1587*37da2899SCharles.Forsyth     FT_UInt32  start, end, start_id;
1588*37da2899SCharles.Forsyth 
1589*37da2899SCharles.Forsyth 
1590*37da2899SCharles.Forsyth     for ( ; num_groups > 0; num_groups-- )
1591*37da2899SCharles.Forsyth     {
1592*37da2899SCharles.Forsyth       start    = TT_NEXT_ULONG( p );
1593*37da2899SCharles.Forsyth       end      = TT_NEXT_ULONG( p );
1594*37da2899SCharles.Forsyth       start_id = TT_NEXT_ULONG( p );
1595*37da2899SCharles.Forsyth 
1596*37da2899SCharles.Forsyth       if ( char_code < start )
1597*37da2899SCharles.Forsyth         break;
1598*37da2899SCharles.Forsyth 
1599*37da2899SCharles.Forsyth       if ( char_code <= end )
1600*37da2899SCharles.Forsyth       {
1601*37da2899SCharles.Forsyth         result = (FT_UInt)( start_id + char_code - start );
1602*37da2899SCharles.Forsyth         break;
1603*37da2899SCharles.Forsyth       }
1604*37da2899SCharles.Forsyth     }
1605*37da2899SCharles.Forsyth     return result;
1606*37da2899SCharles.Forsyth   }
1607*37da2899SCharles.Forsyth 
1608*37da2899SCharles.Forsyth 
1609*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_UInt )
tt_cmap12_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1610*37da2899SCharles.Forsyth   tt_cmap12_char_next( TT_CMap     cmap,
1611*37da2899SCharles.Forsyth                        FT_UInt32  *pchar_code )
1612*37da2899SCharles.Forsyth   {
1613*37da2899SCharles.Forsyth     FT_Byte*   table      = cmap->data;
1614*37da2899SCharles.Forsyth     FT_UInt32  result     = 0;
1615*37da2899SCharles.Forsyth     FT_UInt32  char_code  = *pchar_code + 1;
1616*37da2899SCharles.Forsyth     FT_UInt    gindex     = 0;
1617*37da2899SCharles.Forsyth     FT_Byte*   p          = table + 12;
1618*37da2899SCharles.Forsyth     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1619*37da2899SCharles.Forsyth     FT_UInt32  start, end, start_id;
1620*37da2899SCharles.Forsyth 
1621*37da2899SCharles.Forsyth 
1622*37da2899SCharles.Forsyth     p = table + 16;
1623*37da2899SCharles.Forsyth 
1624*37da2899SCharles.Forsyth     for ( ; num_groups > 0; num_groups-- )
1625*37da2899SCharles.Forsyth     {
1626*37da2899SCharles.Forsyth       start    = TT_NEXT_ULONG( p );
1627*37da2899SCharles.Forsyth       end      = TT_NEXT_ULONG( p );
1628*37da2899SCharles.Forsyth       start_id = TT_NEXT_ULONG( p );
1629*37da2899SCharles.Forsyth 
1630*37da2899SCharles.Forsyth       if ( char_code < start )
1631*37da2899SCharles.Forsyth         char_code = start;
1632*37da2899SCharles.Forsyth 
1633*37da2899SCharles.Forsyth       if ( char_code <= end )
1634*37da2899SCharles.Forsyth       {
1635*37da2899SCharles.Forsyth         gindex = (FT_UInt)(char_code - start + start_id);
1636*37da2899SCharles.Forsyth         if ( gindex != 0 )
1637*37da2899SCharles.Forsyth         {
1638*37da2899SCharles.Forsyth           result = char_code;
1639*37da2899SCharles.Forsyth           goto Exit;
1640*37da2899SCharles.Forsyth         }
1641*37da2899SCharles.Forsyth       }
1642*37da2899SCharles.Forsyth     }
1643*37da2899SCharles.Forsyth 
1644*37da2899SCharles.Forsyth   Exit:
1645*37da2899SCharles.Forsyth     *pchar_code = result;
1646*37da2899SCharles.Forsyth     return gindex;
1647*37da2899SCharles.Forsyth   }
1648*37da2899SCharles.Forsyth 
1649*37da2899SCharles.Forsyth 
1650*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
1651*37da2899SCharles.Forsyth   const TT_CMap_ClassRec  tt_cmap12_class_rec =
1652*37da2899SCharles.Forsyth   {
1653*37da2899SCharles.Forsyth     {
1654*37da2899SCharles.Forsyth       sizeof ( TT_CMapRec ),
1655*37da2899SCharles.Forsyth 
1656*37da2899SCharles.Forsyth       (FT_CMap_InitFunc)     tt_cmap_init,
1657*37da2899SCharles.Forsyth       (FT_CMap_DoneFunc)     NULL,
1658*37da2899SCharles.Forsyth       (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
1659*37da2899SCharles.Forsyth       (FT_CMap_CharNextFunc) tt_cmap12_char_next
1660*37da2899SCharles.Forsyth     },
1661*37da2899SCharles.Forsyth     12,
1662*37da2899SCharles.Forsyth     (TT_CMap_ValidateFunc)   tt_cmap12_validate
1663*37da2899SCharles.Forsyth   };
1664*37da2899SCharles.Forsyth 
1665*37da2899SCharles.Forsyth 
1666*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_12 */
1667*37da2899SCharles.Forsyth 
1668*37da2899SCharles.Forsyth 
1669*37da2899SCharles.Forsyth   static const TT_CMap_Class  tt_cmap_classes[] =
1670*37da2899SCharles.Forsyth   {
1671*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_0
1672*37da2899SCharles.Forsyth     &tt_cmap0_class_rec,
1673*37da2899SCharles.Forsyth #endif
1674*37da2899SCharles.Forsyth 
1675*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_2
1676*37da2899SCharles.Forsyth     &tt_cmap2_class_rec,
1677*37da2899SCharles.Forsyth #endif
1678*37da2899SCharles.Forsyth 
1679*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_4
1680*37da2899SCharles.Forsyth     &tt_cmap4_class_rec,
1681*37da2899SCharles.Forsyth #endif
1682*37da2899SCharles.Forsyth 
1683*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_6
1684*37da2899SCharles.Forsyth     &tt_cmap6_class_rec,
1685*37da2899SCharles.Forsyth #endif
1686*37da2899SCharles.Forsyth 
1687*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_8
1688*37da2899SCharles.Forsyth     &tt_cmap8_class_rec,
1689*37da2899SCharles.Forsyth #endif
1690*37da2899SCharles.Forsyth 
1691*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_10
1692*37da2899SCharles.Forsyth     &tt_cmap10_class_rec,
1693*37da2899SCharles.Forsyth #endif
1694*37da2899SCharles.Forsyth 
1695*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_12
1696*37da2899SCharles.Forsyth     &tt_cmap12_class_rec,
1697*37da2899SCharles.Forsyth #endif
1698*37da2899SCharles.Forsyth 
1699*37da2899SCharles.Forsyth     NULL,
1700*37da2899SCharles.Forsyth   };
1701*37da2899SCharles.Forsyth 
1702*37da2899SCharles.Forsyth 
1703*37da2899SCharles.Forsyth   /* parse the `cmap' table and build the corresponding TT_CMap objects */
1704*37da2899SCharles.Forsyth   /* in the current face                                                */
1705*37da2899SCharles.Forsyth   /*                                                                    */
1706*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
tt_face_build_cmaps(TT_Face face)1707*37da2899SCharles.Forsyth   tt_face_build_cmaps( TT_Face  face )
1708*37da2899SCharles.Forsyth   {
1709*37da2899SCharles.Forsyth     FT_Byte*           table = face->cmap_table;
1710*37da2899SCharles.Forsyth     FT_Byte*           limit = table + face->cmap_size;
1711*37da2899SCharles.Forsyth     FT_UInt volatile   num_cmaps;
1712*37da2899SCharles.Forsyth     FT_Byte* volatile  p     = table;
1713*37da2899SCharles.Forsyth 
1714*37da2899SCharles.Forsyth 
1715*37da2899SCharles.Forsyth     if ( p + 4 > limit )
1716*37da2899SCharles.Forsyth       return FT_Err_Invalid_Table;
1717*37da2899SCharles.Forsyth 
1718*37da2899SCharles.Forsyth     /* only recognize format 0 */
1719*37da2899SCharles.Forsyth     if ( TT_NEXT_USHORT( p ) != 0 )
1720*37da2899SCharles.Forsyth     {
1721*37da2899SCharles.Forsyth       p -= 2;
1722*37da2899SCharles.Forsyth       FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n",
1723*37da2899SCharles.Forsyth                  TT_PEEK_USHORT( p ) ));
1724*37da2899SCharles.Forsyth       return FT_Err_Invalid_Table;
1725*37da2899SCharles.Forsyth     }
1726*37da2899SCharles.Forsyth 
1727*37da2899SCharles.Forsyth     num_cmaps = TT_NEXT_USHORT( p );
1728*37da2899SCharles.Forsyth 
1729*37da2899SCharles.Forsyth     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
1730*37da2899SCharles.Forsyth     {
1731*37da2899SCharles.Forsyth       FT_CharMapRec  charmap;
1732*37da2899SCharles.Forsyth       FT_UInt32      offset;
1733*37da2899SCharles.Forsyth 
1734*37da2899SCharles.Forsyth 
1735*37da2899SCharles.Forsyth       charmap.platform_id = TT_NEXT_USHORT( p );
1736*37da2899SCharles.Forsyth       charmap.encoding_id = TT_NEXT_USHORT( p );
1737*37da2899SCharles.Forsyth       charmap.face        = FT_FACE( face );
1738*37da2899SCharles.Forsyth       charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
1739*37da2899SCharles.Forsyth       offset              = TT_NEXT_ULONG( p );
1740*37da2899SCharles.Forsyth 
1741*37da2899SCharles.Forsyth       if ( offset && table + offset + 2 < limit )
1742*37da2899SCharles.Forsyth       {
1743*37da2899SCharles.Forsyth         FT_Byte*                       cmap   = table + offset;
1744*37da2899SCharles.Forsyth         FT_UInt                        format = TT_PEEK_USHORT( cmap );
1745*37da2899SCharles.Forsyth         const TT_CMap_Class* volatile  pclazz = tt_cmap_classes;
1746*37da2899SCharles.Forsyth         TT_CMap_Class                  clazz;
1747*37da2899SCharles.Forsyth 
1748*37da2899SCharles.Forsyth 
1749*37da2899SCharles.Forsyth         for ( ; *pclazz; pclazz++ )
1750*37da2899SCharles.Forsyth         {
1751*37da2899SCharles.Forsyth           clazz = *pclazz;
1752*37da2899SCharles.Forsyth           if ( clazz->format == format )
1753*37da2899SCharles.Forsyth           {
1754*37da2899SCharles.Forsyth             volatile TT_ValidatorRec  valid;
1755*37da2899SCharles.Forsyth 
1756*37da2899SCharles.Forsyth 
1757*37da2899SCharles.Forsyth             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
1758*37da2899SCharles.Forsyth                                FT_VALIDATE_DEFAULT );
1759*37da2899SCharles.Forsyth 
1760*37da2899SCharles.Forsyth             valid.num_glyphs = (FT_UInt)face->root.num_glyphs;
1761*37da2899SCharles.Forsyth 
1762*37da2899SCharles.Forsyth             if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 )
1763*37da2899SCharles.Forsyth             {
1764*37da2899SCharles.Forsyth               /* validate this cmap sub-table */
1765*37da2899SCharles.Forsyth               clazz->validate( cmap, FT_VALIDATOR( &valid ) );
1766*37da2899SCharles.Forsyth             }
1767*37da2899SCharles.Forsyth 
1768*37da2899SCharles.Forsyth             if ( valid.validator.error == 0 )
1769*37da2899SCharles.Forsyth               (void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL );
1770*37da2899SCharles.Forsyth             else
1771*37da2899SCharles.Forsyth             {
1772*37da2899SCharles.Forsyth               FT_ERROR(( "tt_face_build_cmaps:" ));
1773*37da2899SCharles.Forsyth               FT_ERROR(( " broken cmap sub-table ignored!\n" ));
1774*37da2899SCharles.Forsyth             }
1775*37da2899SCharles.Forsyth           }
1776*37da2899SCharles.Forsyth         }
1777*37da2899SCharles.Forsyth       }
1778*37da2899SCharles.Forsyth     }
1779*37da2899SCharles.Forsyth 
1780*37da2899SCharles.Forsyth     return 0;
1781*37da2899SCharles.Forsyth   }
1782*37da2899SCharles.Forsyth 
1783*37da2899SCharles.Forsyth 
1784*37da2899SCharles.Forsyth /* END */
1785