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